home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1995 June / MacFormat 25.iso / Shareware City / Developers / OutOfPhase1.1 Source / OutOfPhase Folder / WaveTableWindow.c < prev    next >
Text File  |  1994-12-28  |  75KB  |  2,436 lines

  1. /* WaveTableWindow.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "WaveTableWindow.h"
  31. #include "MainWindowStuff.h"
  32. #include "CodeCenter.h"
  33. #include "WaveTableList.h"
  34. #include "TextEdit.h"
  35. #include "IconButton.h"
  36. #include "Scroll.h"
  37. #include "SimpleButton.h"
  38. #include "SampleView.h"
  39. #include "WindowDispatcher.h"
  40. #include "WaveTableObject.h"
  41. #include "Memory.h"
  42. #include "Numbers.h"
  43. #include "Array.h"
  44. #include "DataMunging.h"
  45. #include "EditImages.h"
  46. #include "GrowIcon.h"
  47. #include "Main.h"
  48. #include "StringDialog.h"
  49. #include "FindDialog.h"
  50. #include "GlobalWindowMenuList.h"
  51. #include "WaveTableStorage.h"
  52. #include "WaveTableStorageDisplay.h"
  53. #include "SoundOutput.h"
  54. #include "Alert.h"
  55. #include "NumberDialog.h"
  56. #include "WaveTableSizeDialog.h"
  57. #include "CompilerRoot.h"
  58. #include "PcodeObject.h"
  59. #include "PcodeStack.h"
  60. #include "PcodeSystem.h"
  61. #include "FunctionCode.h"
  62.  
  63.  
  64. #define PAGEINCREMENT (1)
  65.  
  66.  
  67. #define EIGHTBITSHIFTFACTOR (18)
  68. #define SIXTEENBITSHIFTFACTOR (10)
  69.  
  70.  
  71. #define WINDOWXSIZE (420)
  72. #define WINDOWYSIZE (300)
  73.  
  74. #define NAMEEDITX (80)
  75. #define NAMEEDITY (1)
  76. #define NAMEEDITWIDTH (80)
  77. #define NAMEEDITHEIGHT (19)
  78.  
  79. #define NAMEX (3)
  80. #define NAMEY (NAMEEDITY + 3)
  81.  
  82. #define FRAMEEDITX (NAMEEDITX)
  83. #define FRAMEEDITY (NAMEEDITY + NAMEEDITHEIGHT + 3)
  84. #define FRAMEEDITWIDTH (NAMEEDITWIDTH)
  85. #define FRAMEEDITHEIGHT (NAMEEDITHEIGHT)
  86.  
  87. #define FRAMEX (NAMEX)
  88. #define FRAMEY (FRAMEEDITY + 3)
  89.  
  90. #define TABLESEDITX (FRAMEEDITX)
  91. #define TABLESEDITY (FRAMEEDITY + FRAMEEDITHEIGHT + 3)
  92. #define TABLESEDITWIDTH (FRAMEEDITWIDTH)
  93. #define TABLESEDITHEIGHT (FRAMEEDITHEIGHT)
  94.  
  95. #define TABLESX (FRAMEX)
  96. #define TABLESY (TABLESEDITY + 3)
  97.  
  98. #define BITS8BUTTONX (10)
  99. #define BITS8BUTTONY (TABLESEDITY + TABLESEDITHEIGHT + 5)
  100. #define BITS8BUTTONWIDTH (32)
  101. #define BITS8BUTTONHEIGHT (32)
  102.  
  103. #define BITS16BUTTONX (BITS8BUTTONX + BITS8BUTTONWIDTH + 1)
  104. #define BITS16BUTTONY (BITS8BUTTONY)
  105. #define BITS16BUTTONWIDTH (BITS8BUTTONWIDTH)
  106. #define BITS16BUTTONHEIGHT (BITS8BUTTONHEIGHT)
  107.  
  108. #define TESTATTACKDURATIONX (TABLESEDITX)
  109. #define TESTATTACKDURATIONY (BITS16BUTTONY + BITS16BUTTONHEIGHT + 5)
  110. #define TESTATTACKDURATIONWIDTH (TABLESEDITWIDTH)
  111. #define TESTATTACKDURATIONHEIGHT (TABLESEDITHEIGHT)
  112.  
  113. #define TESTATTACKX (TABLESX)
  114. #define TESTATTACKY (TESTATTACKDURATIONY + 3)
  115.  
  116. #define TESTDECAYDURATIONX (TESTATTACKDURATIONX)
  117. #define TESTDECAYDURATIONY (TESTATTACKDURATIONY + TESTATTACKDURATIONHEIGHT + 3)
  118. #define TESTDECAYDURATIONWIDTH (TESTATTACKDURATIONWIDTH)
  119. #define TESTDECAYDURATIONHEIGHT (TESTATTACKDURATIONHEIGHT)
  120.  
  121. #define TESTDECAYX (TESTATTACKX)
  122. #define TESTDECAYY (TESTDECAYDURATIONY + 3)
  123.  
  124. #define TESTFREQUENCYX (TESTDECAYDURATIONX)
  125. #define TESTFREQUENCYY (TESTDECAYDURATIONY + TESTDECAYDURATIONHEIGHT + 3)
  126. #define TESTFREQUENCYWIDTH (TESTDECAYDURATIONWIDTH)
  127. #define TESTFREQUENCYHEIGHT (TESTDECAYDURATIONHEIGHT)
  128.  
  129. #define TESTFREQX (TESTDECAYX)
  130. #define TESTFREQY (TESTFREQUENCYY + 3)
  131.  
  132. #define TESTSAMPLINGRATEX (TESTFREQUENCYX)
  133. #define TESTSAMPLINGRATEY (TESTFREQUENCYY + TESTFREQUENCYHEIGHT + 3)
  134. #define TESTSAMPLINGRATEWIDTH (TESTFREQUENCYWIDTH)
  135. #define TESTSAMPLINGRATEHEIGHT (TESTFREQUENCYHEIGHT)
  136.  
  137. #define TESTSAMPLX (TESTFREQX)
  138. #define TESTSAMPLY (TESTSAMPLINGRATEY + 3)
  139.  
  140. #define TESTBUTTONX (10)
  141. #define TESTBUTTONY (TESTSAMPLINGRATEY + TESTSAMPLINGRATEHEIGHT + 5)
  142. #define TESTBUTTONWIDTH (80)
  143. #define TESTBUTTONHEIGHT (21)
  144.  
  145. #define EXPRESSIONEDITX (-1)
  146. #define EXPRESSIONEDITWIDTH(WindowWidth) ((WindowWidth) + 2)
  147. #define EXPRESSIONEDITHEIGHT (80)
  148. #define EXPRESSIONEDITY(WindowHeight) ((WindowHeight) - EXPRESSIONEDITHEIGHT + 1)
  149.  
  150. #define WAVEFORMVIEWX (NAMEEDITX + NAMEEDITWIDTH + 10)
  151. #define WAVEFORMVIEWY (-1)
  152. #define WAVEFORMVIEWWIDTH(WinWidth) ((WinWidth) - WAVEFORMVIEWX + 1)
  153. #define WAVEFORMVIEWHEIGHT(WinHeight) (EXPRESSIONEDITY(WinHeight) - WAVEFORMVIEWY - 16)
  154.  
  155. #define TABLESCROLLY(WinHeight) (WAVEFORMVIEWY + WAVEFORMVIEWHEIGHT(WinHeight) - 1)
  156.  
  157.  
  158. struct WaveTableWindowRec
  159.     {
  160.         MainWindowRec*            MainWindow;
  161.         CodeCenterRec*            CodeCenter;
  162.         WaveTableListRec*        WaveTableList;
  163.         WaveTableObjectRec*    WaveTableObject;
  164.  
  165.         WaveTableStorDispRec*    WaveTableData;
  166.         MyBoolean                        WaveDataModified;
  167.         WaveTableStorDispRec*    UndoBackupWaveTable;
  168.  
  169.         WinType*                        ScreenID;
  170.         TextEditRec*                NameEdit;
  171.         TextEditRec*                FunctionEdit;
  172.         TextEditRec*                NumFramesEdit;
  173.         TextEditRec*                NumTablesEdit;
  174.         TextEditRec*                TestAttackDuration;
  175.         TextEditRec*                TestDecayDuration;
  176.         TextEditRec*                TestFrequency;
  177.         TextEditRec*                TestSamplingRate;
  178.         TextEditRec*                ActiveTextEdit;
  179.         SimpleButtonRec*        TestButton;
  180.         IconButtonRec*            Bits8Button;
  181.         IconButtonRec*            Bits16Button;
  182.         ScrollRec*                    TableScroll;
  183.         long                                CurrentlyVisibleTable;
  184.         GenericWindowRec*        MyGenericWindow; /* how the window event dispatcher knows us */
  185.         MenuItemType*                MyMenuItem;
  186.     };
  187.  
  188.  
  189. /* create a new wave table window. */
  190. WaveTableWindowRec*    NewWaveTableWindow(struct MainWindowRec* MainWindow,
  191.                                             struct WaveTableObjectRec* WaveTableObject,
  192.                                             struct CodeCenterRec* CodeCenter,
  193.                                             struct WaveTableListRec* WaveTableList,
  194.                                             struct WaveTableStorageRec* WaveData,
  195.                                             OrdType WinX, OrdType WinY, OrdType WinWidth, OrdType WinHeight)
  196.     {
  197.         WaveTableWindowRec*        Window;
  198.         char*                                    StringTemp;
  199.         long                                    Scan;
  200.         long                                    Limit;
  201.  
  202.         CheckPtrExistence(MainWindow);
  203.         CheckPtrExistence(WaveTableObject);
  204.         CheckPtrExistence(CodeCenter);
  205.         CheckPtrExistence(WaveTableList);
  206.         CheckPtrExistence(WaveData);
  207.  
  208.         /* deal with window placement */
  209.         if ((WinWidth < 100) || (WinHeight < 100) || ((eOptionKey & CheckModifiers()) != 0))
  210.             {
  211.                 WinX = 1 + WindowOtherEdgeWidths(eDocumentWindow);
  212.                 WinY = 1 + WindowTitleBarHeight(eDocumentWindow);
  213.                 WinWidth = WINDOWXSIZE;
  214.                 WinHeight = WINDOWYSIZE;
  215.             }
  216.         MakeWindowFitOnScreen(&WinX,&WinY,&WinWidth,&WinHeight);
  217.  
  218.         Window = (WaveTableWindowRec*)AllocPtrCanFail(sizeof(WaveTableWindowRec),
  219.             "WaveTableWindowRec");
  220.         if (Window == NIL)
  221.             {
  222.              FailurePoint1:
  223.                 return NIL;
  224.             }
  225.         Window->MainWindow = MainWindow;
  226.         Window->WaveTableObject = WaveTableObject;
  227.         Window->CodeCenter = CodeCenter;
  228.         Window->WaveTableList = WaveTableList;
  229.  
  230.         Window->ScreenID = MakeNewWindow(eDocumentWindow,eWindowClosable,
  231.             eWindowZoomable,eWindowResizable,WinX,WinY,WinWidth,WinHeight,
  232.             (void (*)(void*))&WaveTableWindowUpdator,Window);
  233.         if (Window->ScreenID == 0)
  234.             {
  235.              FailurePoint2:
  236.                 ReleasePtr((char*)Window);
  237.                 goto FailurePoint1;
  238.             }
  239.  
  240.         Window->NameEdit = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  241.             GetScreenFont(),9,NAMEEDITX,NAMEEDITY,NAMEEDITWIDTH,NAMEEDITHEIGHT);
  242.         if (Window->NameEdit == NIL)
  243.             {
  244.              FailurePoint3:
  245.                 KillWindow(Window->ScreenID);
  246.                 goto FailurePoint2;
  247.             }
  248.         StringTemp = WaveTableObjectGetNameCopy(WaveTableObject);
  249.         if (StringTemp == NIL)
  250.             {
  251.              FailurePoint4:
  252.                 DisposeTextEdit(Window->NameEdit);
  253.                 goto FailurePoint3;
  254.             }
  255.         TextEditNewRawData(Window->NameEdit,StringTemp,"\x0a");
  256.         ReleasePtr(StringTemp);
  257.         TextEditHasBeenSaved(Window->NameEdit);
  258.  
  259.         Window->FunctionEdit = NewTextEdit(Window->ScreenID,
  260.             (TEScrollType)(eTEVScrollBar | eTEHScrollBar),GetMonospacedFont(),9,
  261.             EXPRESSIONEDITX,EXPRESSIONEDITY(WinHeight),EXPRESSIONEDITWIDTH(WinWidth),
  262.             EXPRESSIONEDITHEIGHT);
  263.         if (Window->FunctionEdit == NIL)
  264.             {
  265.              FailurePoint5:
  266.                 goto FailurePoint4;
  267.             }
  268.         StringTemp = WaveTableObjectGetFormulaCopy(WaveTableObject);
  269.         SetTextEditTabSize(Window->FunctionEdit,MainWindowGetTabSize(MainWindow));
  270.         if (StringTemp == NIL)
  271.             {
  272.              FailurePoint6:
  273.                 DisposeTextEdit(Window->FunctionEdit);
  274.                 goto FailurePoint5;
  275.             }
  276.         TextEditNewRawData(Window->FunctionEdit,StringTemp,"\x0a");
  277.         ReleasePtr(StringTemp);
  278.         TextEditHasBeenSaved(Window->FunctionEdit);
  279.         SetTextEditAutoIndent(Window->FunctionEdit,True);
  280.  
  281.         Window->NumFramesEdit = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  282.             GetScreenFont(),9,FRAMEEDITX,FRAMEEDITY,FRAMEEDITWIDTH,FRAMEEDITHEIGHT);
  283.         if (Window->NumFramesEdit == NIL)
  284.             {
  285.              FailurePoint7:
  286.                 goto FailurePoint6;
  287.             }
  288.         StringTemp = IntegerToString(WaveTableObjectEntriesPerTable(WaveTableObject));
  289.         if (StringTemp == NIL)
  290.             {
  291.              FailurePoint8:
  292.                 DisposeTextEdit(Window->NumFramesEdit);
  293.                 goto FailurePoint7;
  294.             }
  295.         TextEditNewRawData(Window->NumFramesEdit,StringTemp,"\x0a");
  296.         ReleasePtr(StringTemp);
  297.         TextEditHasBeenSaved(Window->NumFramesEdit);
  298.  
  299.         Window->NumTablesEdit = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  300.             GetScreenFont(),9,TABLESEDITX,TABLESEDITY,TABLESEDITWIDTH,TABLESEDITHEIGHT);
  301.         if (Window->NumTablesEdit == NIL)
  302.             {
  303.              FailurePoint9:
  304.                 goto FailurePoint8;
  305.             }
  306.         StringTemp = IntegerToString(WaveTableObjectGetNumTables(WaveTableObject));
  307.         if (StringTemp == NIL)
  308.             {
  309.              FailurePoint10:
  310.                 DisposeTextEdit(Window->NumTablesEdit);
  311.                 goto FailurePoint9;
  312.             }
  313.         TextEditNewRawData(Window->NumTablesEdit,StringTemp,"\x0a");
  314.         ReleasePtr(StringTemp);
  315.         TextEditHasBeenSaved(Window->NumTablesEdit);
  316.  
  317.         Window->TestAttackDuration = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  318.             GetScreenFont(),9,TESTATTACKDURATIONX,TESTATTACKDURATIONY,TESTATTACKDURATIONWIDTH,
  319.             TESTATTACKDURATIONHEIGHT);
  320.         if (Window->TestAttackDuration == NIL)
  321.             {
  322.              FailurePoint11:
  323.                 goto FailurePoint10;
  324.             }
  325.         StringTemp = LongDoubleToString(WaveTableObjectGetTestAttack(WaveTableObject),
  326.             6,1e-4,1e6);
  327.         if (StringTemp == NIL)
  328.             {
  329.              FailurePoint12:
  330.                 DisposeTextEdit(Window->TestAttackDuration);
  331.                 goto FailurePoint11;
  332.             }
  333.         TextEditNewRawData(Window->TestAttackDuration,StringTemp,"\x0a");
  334.         ReleasePtr(StringTemp);
  335.  
  336.         Window->TestDecayDuration = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  337.             GetScreenFont(),9,TESTDECAYDURATIONX,TESTDECAYDURATIONY,TESTDECAYDURATIONWIDTH,
  338.             TESTDECAYDURATIONHEIGHT);
  339.         if (Window->TestDecayDuration == NIL)
  340.             {
  341.              FailurePoint13:
  342.                 goto FailurePoint12;
  343.             }
  344.         StringTemp = LongDoubleToString(WaveTableObjectGetTestDecay(WaveTableObject),
  345.             6,1e-4,1e6);
  346.         if (StringTemp == NIL)
  347.             {
  348.              FailurePoint14:
  349.                 DisposeTextEdit(Window->TestDecayDuration);
  350.                 goto FailurePoint13;
  351.             }
  352.         TextEditNewRawData(Window->TestDecayDuration,StringTemp,"\x0a");
  353.         ReleasePtr(StringTemp);
  354.  
  355.         Window->Bits8Button = NewIconButtonPreparedBitmaps(Window->ScreenID,BITS8BUTTONX,
  356.             BITS8BUTTONY,BITS8BUTTONWIDTH,BITS8BUTTONHEIGHT,Bits8Unselected,Bits8MouseDown,
  357.             Bits8Selected,Bits8Selected,eIconRadioMode);
  358.         if (Window->Bits8Button == NIL)
  359.             {
  360.              FailurePoint15:
  361.                 goto FailurePoint14;
  362.             }
  363.  
  364.         Window->Bits16Button = NewIconButtonPreparedBitmaps(Window->ScreenID,BITS16BUTTONX,
  365.             BITS16BUTTONY,BITS16BUTTONWIDTH,BITS16BUTTONHEIGHT,Bits16Unselected,
  366.             Bits16MouseDown,Bits16Selected,Bits16Selected,eIconRadioMode);
  367.         if (Window->Bits16Button == NIL)
  368.             {
  369.              FailurePoint16:
  370.                 DisposeIconButton(Window->Bits8Button);
  371.                 goto FailurePoint15;
  372.             }
  373.  
  374.         switch (WaveTableObjectGetNumBits(WaveTableObject))
  375.             {
  376.                 default:
  377.                     EXECUTE(PRERR(ForceAbort,"NewWaveTableWindow:  bad number of bits"));
  378.                     break;
  379.                 case eSample8bit:
  380.                     SetIconButtonState(Window->Bits8Button,True);
  381.                     break;
  382.                 case eSample16bit:
  383.                     SetIconButtonState(Window->Bits16Button,True);
  384.                     break;
  385.             }
  386.  
  387.         Window->TestButton = NewSimpleButton(Window->ScreenID,"Test",
  388.             TESTBUTTONX,TESTBUTTONY,TESTBUTTONWIDTH,TESTBUTTONHEIGHT);
  389.         if (Window->TestButton == NIL)
  390.             {
  391.              FailurePoint17:
  392.                 DisposeIconButton(Window->Bits16Button);
  393.                 goto FailurePoint16;
  394.             }
  395.  
  396.         Window->TableScroll = NewScrollBar(Window->ScreenID,eHScrollBar,
  397.             WAVEFORMVIEWX,TABLESCROLLY(WinHeight),WAVEFORMVIEWWIDTH(WinWidth));
  398.         if (Window->TableScroll == NIL)
  399.             {
  400.              FailurePoint18:
  401.                 DisposeSimpleButton(Window->TestButton);
  402.                 goto FailurePoint17;
  403.             }
  404.         Window->CurrentlyVisibleTable = 0;
  405.  
  406.         Window->WaveTableData = NewWaveTableStorDisp(WaveTableStorageNumBits(WaveData),
  407.             WaveTableStorageNumFramesPerTable(WaveData));
  408.         if (Window->WaveTableData == NIL)
  409.             {
  410.              FailurePoint19:
  411.                 DisposeScrollBar(Window->TableScroll);
  412.                 goto FailurePoint18;
  413.             }
  414.         Limit = WaveTableStorageNumTables(WaveData);
  415.         for (Scan = 0; Scan < Limit; Scan += 1)
  416.             {
  417.                 long                            Index;
  418.                 long                            IndexLimit;
  419.  
  420.                 if (!WaveTableStorDispAppendEntry(Window->WaveTableData))
  421.                     {
  422.                      FailurePoint20:
  423.                         DisposeWaveTableStorDisp(Window->WaveTableData);
  424.                         goto FailurePoint19;
  425.                     }
  426.                 IndexLimit = WaveTableStorageNumFramesPerTable(WaveData);
  427.                 for (Index = 0; Index < IndexLimit; Index += 1)
  428.                     {
  429.                         WaveTableStorDispSetFrame(Window->WaveTableData,Scan,Index,
  430.                             WaveTableStorageGetFrame(WaveData,Scan,Index));
  431.                     }
  432.             }
  433.  
  434.         Window->MyGenericWindow = CheckInNewWindow(Window->ScreenID,Window,
  435.             (void (*)(void*,MyBoolean,OrdType,OrdType,ModifierFlags))&WaveTableWindowDoIdle,
  436.             (void (*)(void*))&WaveTableWindowBecomeActive,
  437.             (void (*)(void*))&WaveTableWindowBecomeInactive,
  438.             (void (*)(void*))&WaveTableWindowJustResized,
  439.             (void (*)(OrdType,OrdType,ModifierFlags,void*))&WaveTableWindowDoMouseDown,
  440.             (void (*)(unsigned char,ModifierFlags,void*))&WaveTableWindowDoKeyDown,
  441.             (void (*)(void*))&WaveTableWindowClose,
  442.             (void (*)(void*))&WaveTableWindowMenuSetup,
  443.             (void (*)(void*,MenuItemType*))&WaveTableWindowDoMenuCommand);
  444.         if (Window->MyGenericWindow == NIL)
  445.             {
  446.              FailurePoint21:
  447.                 goto FailurePoint20;
  448.             }
  449.  
  450.         Window->TestFrequency = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  451.             GetScreenFont(),9,TESTFREQUENCYX,TESTFREQUENCYY,TESTFREQUENCYWIDTH,
  452.             TESTFREQUENCYHEIGHT);
  453.         if (Window->TestFrequency == NIL)
  454.             {
  455.              FailurePoint22:
  456.                 CheckOutDyingWindow(Window->MyGenericWindow);
  457.                 goto FailurePoint21;
  458.             }
  459.         StringTemp = LongDoubleToString(WaveTableObjectGetTestPitch(WaveTableObject),
  460.             13,1e-4,1e6);
  461.         if (StringTemp == NIL)
  462.             {
  463.              FailurePoint23:
  464.                 DisposeTextEdit(Window->TestFrequency);
  465.                 goto FailurePoint22;
  466.             }
  467.         TextEditNewRawData(Window->TestFrequency,StringTemp,"\x0a");
  468.         ReleasePtr(StringTemp);
  469.  
  470.         Window->TestSamplingRate = NewTextEdit(Window->ScreenID,eTENoScrollBars,
  471.             GetScreenFont(),9,TESTSAMPLINGRATEX,TESTSAMPLINGRATEY,TESTSAMPLINGRATEWIDTH,
  472.             TESTSAMPLINGRATEHEIGHT);
  473.         if (Window->TestSamplingRate == NIL)
  474.             {
  475.              FailurePoint24:
  476.                 goto FailurePoint23;
  477.             }
  478.         StringTemp = IntegerToString(WaveTableObjectGetTestSamplingRate(WaveTableObject));
  479.         if (StringTemp == NIL)
  480.             {
  481.              FailurePoint25:
  482.                 DisposeTextEdit(Window->TestSamplingRate);
  483.                 goto FailurePoint24;
  484.             }
  485.         TextEditNewRawData(Window->TestSamplingRate,StringTemp,"\x0a");
  486.         ReleasePtr(StringTemp);
  487.  
  488.         Window->MyMenuItem = MakeNewMenuItem(mmWindowMenu,"x",0);
  489.         if (Window->MyMenuItem == NIL)
  490.             {
  491.              FailurePoint26:
  492.                 goto FailurePoint25;
  493.             }
  494.         if (!RegisterWindowMenuItem(Window->MyMenuItem,(void (*)(void*))&ActivateThisWindow,
  495.             Window->ScreenID))
  496.             {
  497.              FailurePoint27:
  498.                 KillMenuItem(Window->MyMenuItem);
  499.                 goto FailurePoint26;
  500.             }
  501.  
  502.         Window->WaveDataModified = False;
  503.         Window->ActiveTextEdit = Window->FunctionEdit;
  504.         Window->UndoBackupWaveTable = NIL;
  505.         WaveTableWindowResetTitlebar(Window);
  506.         WaveTableWindowUpdateScrollBar(Window);
  507.  
  508.         return Window;
  509.     }
  510.  
  511.  
  512. /* write back modified data and dispose of the wave table window */
  513. void                                DisposeWaveTableWindow(WaveTableWindowRec* Window)
  514.     {
  515.         CheckPtrExistence(Window);
  516.  
  517.         /* save data */
  518.         if (!WaveTableWindowWritebackModifiedData(Window))
  519.             {
  520.                 /* failed -- now what? */
  521.             }
  522.  
  523.         WaveTableObjectClosingWindowNotify(Window->WaveTableObject,
  524.             GetWindowXStart(Window->ScreenID),GetWindowYStart(Window->ScreenID),
  525.             GetWindowWidth(Window->ScreenID),GetWindowHeight(Window->ScreenID));
  526.         DeregisterWindowMenuItem(Window->MyMenuItem);
  527.         KillMenuItem(Window->MyMenuItem);
  528.         CheckOutDyingWindow(Window->MyGenericWindow);
  529.         DisposeWaveTableStorDisp(Window->WaveTableData);
  530.         if (Window->UndoBackupWaveTable != NIL)
  531.             {
  532.                 DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  533.             }
  534.         DisposeScrollBar(Window->TableScroll);
  535.         DisposeIconButton(Window->Bits16Button);
  536.         DisposeIconButton(Window->Bits8Button);
  537.         DisposeTextEdit(Window->NameEdit);
  538.         DisposeTextEdit(Window->FunctionEdit);
  539.         DisposeTextEdit(Window->NumFramesEdit);
  540.         DisposeTextEdit(Window->NumTablesEdit);
  541.         DisposeTextEdit(Window->TestAttackDuration);
  542.         DisposeTextEdit(Window->TestDecayDuration);
  543.         DisposeTextEdit(Window->TestFrequency);
  544.         DisposeTextEdit(Window->TestSamplingRate);
  545.         DisposeSimpleButton(Window->TestButton);
  546.         KillWindow(Window->ScreenID);
  547.         ReleasePtr((char*)Window);
  548.     }
  549.  
  550.  
  551. /* return True if the data has been modified since the last time the file was saved */
  552. MyBoolean                        HasWaveTableWindowBeenModified(WaveTableWindowRec* Window)
  553.     {
  554.         CheckPtrExistence(Window);
  555.         return Window->WaveDataModified
  556.             || TextEditDoesItNeedToBeSaved(Window->NameEdit)
  557.             || TextEditDoesItNeedToBeSaved(Window->FunctionEdit)
  558.             || TextEditDoesItNeedToBeSaved(Window->TestAttackDuration)
  559.             || TextEditDoesItNeedToBeSaved(Window->TestDecayDuration)
  560.             || TextEditDoesItNeedToBeSaved(Window->TestFrequency)
  561.             || TextEditDoesItNeedToBeSaved(Window->TestSamplingRate);
  562.     }
  563.  
  564.  
  565. /* bring the window to the top and give it the focus */
  566. void                                WaveTableWindowBringToTop(WaveTableWindowRec* Window)
  567.     {
  568.         CheckPtrExistence(Window);
  569.         ActivateThisWindow(Window->ScreenID);
  570.     }
  571.  
  572.  
  573. void                                WaveTableWindowDoIdle(WaveTableWindowRec* Window,
  574.                                             MyBoolean CheckCursorFlag, OrdType XLoc, OrdType YLoc,
  575.                                             ModifierFlags Modifiers)
  576.     {
  577.         CheckPtrExistence(Window);
  578.         if (Window->ActiveTextEdit != NIL)
  579.             {
  580.                 TextEditUpdateCursor(Window->ActiveTextEdit);
  581.             }
  582.         if (CheckCursorFlag)
  583.             {
  584.                 if (TextEditIBeamTest(Window->NameEdit,XLoc,YLoc)
  585.                     || TextEditIBeamTest(Window->FunctionEdit,XLoc,YLoc)
  586.                     || TextEditIBeamTest(Window->NumFramesEdit,XLoc,YLoc)
  587.                     || TextEditIBeamTest(Window->NumTablesEdit,XLoc,YLoc)
  588.                     || TextEditIBeamTest(Window->TestAttackDuration,XLoc,YLoc)
  589.                     || TextEditIBeamTest(Window->TestDecayDuration,XLoc,YLoc)
  590.                     || TextEditIBeamTest(Window->TestFrequency,XLoc,YLoc)
  591.                     || TextEditIBeamTest(Window->TestSamplingRate,XLoc,YLoc))
  592.                     {
  593.                         SetIBeamCursor();
  594.                     }
  595.                 else if ((XLoc >= WAVEFORMVIEWX) && (YLoc >= WAVEFORMVIEWY)
  596.                     && (XLoc < WAVEFORMVIEWX + WAVEFORMVIEWWIDTH(GetWindowWidth(Window->ScreenID)))
  597.                     && (YLoc < WAVEFORMVIEWY
  598.                     + WAVEFORMVIEWHEIGHT(GetWindowHeight(Window->ScreenID)) - 15))
  599.                     {
  600.                         SetSampleInsertionCursor();
  601.                     }
  602.                 else
  603.                     {
  604.                         SetArrowCursor();
  605.                     }
  606.             }
  607.     }
  608.  
  609.  
  610. void                                WaveTableWindowBecomeActive(WaveTableWindowRec* Window)
  611.     {
  612.         OrdType                        XSize;
  613.         OrdType                        YSize;
  614.  
  615.         CheckPtrExistence(Window);
  616.         if (Window->ActiveTextEdit != NIL)
  617.             {
  618.                 EnableTextEditSelection(Window->ActiveTextEdit);
  619.             }
  620.         EnableScrollBar(Window->TableScroll);
  621.         XSize = GetWindowWidth(Window->ScreenID);
  622.         YSize = GetWindowHeight(Window->ScreenID);
  623.         SetClipRect(Window->ScreenID,XSize - 15,YSize - 15,XSize,YSize);
  624.         DrawBitmap(Window->ScreenID,XSize-15,YSize-15,GetGrowIcon(True/*enablegrowicon*/));
  625.     }
  626.  
  627.  
  628. void                                WaveTableWindowBecomeInactive(WaveTableWindowRec* Window)
  629.     {
  630.         OrdType                        XSize;
  631.         OrdType                        YSize;
  632.  
  633.         CheckPtrExistence(Window);
  634.         if (Window->ActiveTextEdit != NIL)
  635.             {
  636.                 DisableTextEditSelection(Window->ActiveTextEdit);
  637.             }
  638.         DisableScrollBar(Window->TableScroll);
  639.         XSize = GetWindowWidth(Window->ScreenID);
  640.         YSize = GetWindowHeight(Window->ScreenID);
  641.         SetClipRect(Window->ScreenID,XSize - 15,YSize - 15,XSize,YSize);
  642.         DrawBitmap(Window->ScreenID,XSize-15,YSize-15,GetGrowIcon(False/*disablegrowicon*/));
  643.     }
  644.  
  645.  
  646. void                                WaveTableWindowJustResized(WaveTableWindowRec* Window)
  647.     {
  648.         OrdType                        XSize;
  649.         OrdType                        YSize;
  650.  
  651.         CheckPtrExistence(Window);
  652.         XSize = GetWindowWidth(Window->ScreenID);
  653.         YSize = GetWindowHeight(Window->ScreenID);
  654.         SetClipRect(Window->ScreenID,0,0,XSize,YSize);
  655.         DrawBoxErase(Window->ScreenID,0,0,XSize,YSize);
  656.  
  657.         SetTextEditPosition(Window->FunctionEdit,EXPRESSIONEDITX,EXPRESSIONEDITY(YSize),
  658.             EXPRESSIONEDITWIDTH(XSize),EXPRESSIONEDITHEIGHT);
  659.         SetScrollLocation(Window->TableScroll,WAVEFORMVIEWX,TABLESCROLLY(YSize),
  660.             WAVEFORMVIEWWIDTH(XSize));
  661.     }
  662.  
  663.  
  664. static void                    WaveTableWindowScrollHook(long Parameter, ScrollType How,
  665.                                             WaveTableWindowRec* Window)
  666.     {
  667.         CheckPtrExistence(Window);
  668.         switch (How)
  669.             {
  670.                 case eScrollToPosition:
  671.                     Window->CurrentlyVisibleTable = Parameter;
  672.                     WaveTableWindowUpdateScrollBar(Window);
  673.                     WaveTableWindowRedrawTable(Window);
  674.                     break;
  675.                 case eScrollPageMinus:
  676.                     Window->CurrentlyVisibleTable -= PAGEINCREMENT;
  677.                     if (Window->CurrentlyVisibleTable < 0)
  678.                         {
  679.                             Window->CurrentlyVisibleTable = 0;
  680.                         }
  681.                     WaveTableWindowUpdateScrollBar(Window);
  682.                     WaveTableWindowRedrawTable(Window);
  683.                     break;
  684.                 case eScrollPagePlus:
  685.                     Window->CurrentlyVisibleTable += PAGEINCREMENT;
  686.                     if (Window->CurrentlyVisibleTable > WaveTableWindowGetNumTables(Window) - 1)
  687.                         {
  688.                             Window->CurrentlyVisibleTable = WaveTableWindowGetNumTables(Window) - 1;
  689.                         }
  690.                     if (Window->CurrentlyVisibleTable < 0)
  691.                         {
  692.                             /* just in case there are 0 tables -- this makes index become -1 */
  693.                             Window->CurrentlyVisibleTable = 0;
  694.                         }
  695.                     WaveTableWindowUpdateScrollBar(Window);
  696.                     WaveTableWindowRedrawTable(Window);
  697.                     break;
  698.                 case eScrollLineMinus:
  699.                     Window->CurrentlyVisibleTable -= 1;
  700.                     if (Window->CurrentlyVisibleTable < 0)
  701.                         {
  702.                             Window->CurrentlyVisibleTable = 0;
  703.                         }
  704.                     WaveTableWindowUpdateScrollBar(Window);
  705.                     WaveTableWindowRedrawTable(Window);
  706.                     break;
  707.                 case eScrollLinePlus:
  708.                     Window->CurrentlyVisibleTable += 1;
  709.                     if (Window->CurrentlyVisibleTable > WaveTableWindowGetNumTables(Window) - 1)
  710.                         {
  711.                             Window->CurrentlyVisibleTable = WaveTableWindowGetNumTables(Window) - 1;
  712.                         }
  713.                     if (Window->CurrentlyVisibleTable < 0)
  714.                         {
  715.                             /* just in case there are 0 tables -- this makes index become -1 */
  716.                             Window->CurrentlyVisibleTable = 0;
  717.                         }
  718.                     WaveTableWindowUpdateScrollBar(Window);
  719.                     WaveTableWindowRedrawTable(Window);
  720.                     break;
  721.                 default:
  722.                     EXECUTE(PRERR(AllowResume,"WaveTableWindowScrollHook:  Unknown scroll opcode"));
  723.                     break;
  724.             }
  725.     }
  726.  
  727.  
  728. #define SOUNDBUFFERLENGTHBYTES (16384)
  729. #define NUMSOUNDBUFFERS (4)
  730. static void                    WaveTablePlayIt(WaveTableWindowRec* Window)
  731.     {
  732.         long                                        NumTables;
  733.         long                                        Scan;
  734.         SoundOutputNumBits            SoundChannelBits;
  735.         largefixedsigned**            ReferenceArray;
  736.         unsigned long                        WaveformIndex;
  737.         unsigned long                        WaveformIncrementor;
  738.         unsigned long                        WaveformMask;
  739.         long                                        NumberOfIterationsAttack;
  740.         long                                        NumberOfIterationsDecay;
  741.         long                                        PlaybackSamplingRate;
  742.         void*                                        OutputBuffer;
  743.         long                                        OutputIndex;
  744.  
  745.         /* get the number of tables */
  746.         NumTables = WaveTableStorDispNumTables(Window->WaveTableData);
  747.  
  748.         /* fill in the buffer */
  749.         ReferenceArray = (largefixedsigned**)AllocPtrCanFail(sizeof(largefixedsigned*)
  750.             * NumTables,"WaveTablePlayIt:  ReferenceArray");
  751.         if (ReferenceArray == NIL)
  752.             {
  753.                 AlertHalt("There is not enough memory available to play the sample.",NIL);
  754.              FailurePoint1:
  755.                 return;
  756.             }
  757.         for (Scan = 0; Scan < WaveTableStorDispNumTables(Window->WaveTableData); Scan += 1)
  758.             {
  759.                 ReferenceArray[Scan] = WaveTableStorDispGetTable(Window->WaveTableData,Scan);
  760.             }
  761.  
  762.         /* how many bits should be used for playback */
  763.         switch (WaveTableStorDispNumBits(Window->WaveTableData))
  764.             {
  765.                 default:
  766.                     EXECUTE(PRERR(ForceAbort,"WaveTablePlayIt:  bad number of bits"));
  767.                     break;
  768.                 case eSample16bit:
  769.                     SoundChannelBits = e16bit;
  770.                     break;
  771.                 case eSample8bit:
  772.                     SoundChannelBits = e8bit;
  773.                     break;
  774.             }
  775.  
  776.         /* playback at what sampling rate */
  777.         PlaybackSamplingRate = WaveTableWindowGetTestSamplingRate(Window);
  778.         if (PlaybackSamplingRate < MINSAMPLINGRATE)
  779.             {
  780.                 PlaybackSamplingRate = MINSAMPLINGRATE;
  781.             }
  782.         if (PlaybackSamplingRate > MAXSAMPLINGRATE)
  783.             {
  784.                 PlaybackSamplingRate = MAXSAMPLINGRATE;
  785.             }
  786.  
  787.         /* this is the initial index into the wave table */
  788.         WaveformIndex = 0;
  789.  
  790.         /* this is the 16.16 bit fixed point number used to increment the index */
  791.         /* into the wave table */
  792.         WaveformIncrementor = WaveTableWindowGetNumFramesPerTable(Window)
  793.             * WaveTableWindowGetPitch(Window) / PlaybackSamplingRate * 65536;
  794.  
  795.         /* this is used to mask off all garbage bits from the index when */
  796.         /* looking values up in the wave table */
  797.         WaveformMask = WaveTableWindowGetNumFramesPerTable(Window) - 1;
  798.  
  799.         /* the number of times each wave slice has to be used */
  800.         NumberOfIterationsAttack = WaveTableWindowGetAscendingDuration(Window)
  801.             / (double)NumTables * PlaybackSamplingRate;
  802.         NumberOfIterationsDecay = WaveTableWindowGetDescendingDuration(Window)
  803.             / (double)NumTables * PlaybackSamplingRate;
  804.  
  805.         if (!OpenSoundChannel(PlaybackSamplingRate,eMono,SoundChannelBits,
  806.             SOUNDBUFFERLENGTHBYTES,NUMSOUNDBUFFERS,NUMSOUNDBUFFERS))
  807.             {
  808.                 AlertHalt("Unable top open the sound device.",NIL);
  809.              FailurePoint2:
  810.                 ReleasePtr((char*)ReferenceArray);
  811.                 goto FailurePoint1;
  812.             }
  813.         OutputIndex = 0;
  814.         do
  815.             {
  816.                 OutputBuffer = CheckOutSoundBuffer();
  817.             } while (OutputBuffer == NIL);
  818.  
  819.         if (SoundChannelBits == e16bit)
  820.             {
  821.                 for (Scan = 0; Scan < NumTables; Scan += 1)
  822.                     {
  823.                         largefixedsigned*            Buffer = ReferenceArray[Scan];
  824.                         long                                    Index;
  825.  
  826.                         for (Index = 0; Index < NumberOfIterationsAttack; Index += 1)
  827.                             {
  828.                                 unsigned long                    SampleReference;
  829.                                 signed short                    Left;
  830.                                 signed short                    Right;
  831.                                 signed long                        Fraction;
  832.  
  833.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  834.                                 Left = Buffer[SampleReference] >> SIXTEENBITSHIFTFACTOR;
  835.                                 Right = Buffer[SampleReference + 1] >> SIXTEENBITSHIFTFACTOR;
  836.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  837.                                 WaveformIndex += WaveformIncrementor;
  838.                                 ((short*)OutputBuffer)[OutputIndex] = (Left * (0x8000 - Fraction)
  839.                                     + Right * Fraction) >> 15;
  840.                                 OutputIndex += 1;
  841.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(short))
  842.                                     {
  843.                                         SubmitBuffer((char*)OutputBuffer,SOUNDBUFFERLENGTHBYTES
  844.                                             / sizeof(short),NIL,NIL);
  845.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  846.                                             {
  847.                                                 goto EscapePoint;
  848.                                             }
  849.                                         do
  850.                                             {
  851.                                                 OutputBuffer = CheckOutSoundBuffer();
  852.                                             } while (OutputBuffer == NIL);
  853.                                         OutputIndex = 0;
  854.                                     }
  855.                             }
  856.                     }
  857.             }
  858.          else
  859.             {
  860.                 for (Scan = 0; Scan < NumTables; Scan += 1)
  861.                     {
  862.                         largefixedsigned*            Buffer = ReferenceArray[Scan];
  863.                         long                                    Index;
  864.  
  865.                         for (Index = 0; Index < NumberOfIterationsAttack; Index += 1)
  866.                             {
  867.                                 unsigned long                    SampleReference;
  868.                                 signed short                    Left;
  869.                                 signed short                    Right;
  870.                                 signed long                        Fraction;
  871.  
  872.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  873.                                 Left = Buffer[SampleReference] >> EIGHTBITSHIFTFACTOR;
  874.                                 Right = Buffer[SampleReference + 1] >> EIGHTBITSHIFTFACTOR;
  875.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  876.                                 WaveformIndex += WaveformIncrementor;
  877.                                 ((char*)OutputBuffer)[OutputIndex] = (Left * (0x8000 - Fraction)
  878.                                     + Right * Fraction) >> 15;
  879.                                 OutputIndex += 1;
  880.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(char))
  881.                                     {
  882.                                         SubmitBuffer((char*)OutputBuffer,SOUNDBUFFERLENGTHBYTES
  883.                                             / sizeof(char),NIL,NIL);
  884.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  885.                                             {
  886.                                                 goto EscapePoint;
  887.                                             }
  888.                                         do
  889.                                             {
  890.                                                 OutputBuffer = CheckOutSoundBuffer();
  891.                                             } while (OutputBuffer == NIL);
  892.                                         OutputIndex = 0;
  893.                                     }
  894.                             }
  895.                     }
  896.             }
  897.  
  898.         if (SoundChannelBits == e16bit)
  899.             {
  900.                 for (Scan = NumTables - 1; Scan >= 0; Scan -= 1)
  901.                     {
  902.                         largefixedsigned*            Buffer = ReferenceArray[Scan];
  903.                         long                                    Index;
  904.  
  905.                         for (Index = 0; Index < NumberOfIterationsDecay; Index += 1)
  906.                             {
  907.                                 unsigned long                    SampleReference;
  908.                                 signed short                    Left;
  909.                                 signed short                    Right;
  910.                                 signed long                        Fraction;
  911.  
  912.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  913.                                 Left = Buffer[SampleReference] >> SIXTEENBITSHIFTFACTOR;
  914.                                 Right = Buffer[SampleReference + 1] >> SIXTEENBITSHIFTFACTOR;
  915.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  916.                                 WaveformIndex += WaveformIncrementor;
  917.                                 ((short*)OutputBuffer)[OutputIndex] = (Left * (0x8000 - Fraction)
  918.                                     + Right * Fraction) >> 15;
  919.                                 OutputIndex += 1;
  920.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(short))
  921.                                     {
  922.                                         SubmitBuffer((char*)OutputBuffer,SOUNDBUFFERLENGTHBYTES
  923.                                             / sizeof(short),NIL,NIL);
  924.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  925.                                             {
  926.                                                 goto EscapePoint;
  927.                                             }
  928.                                         do
  929.                                             {
  930.                                                 OutputBuffer = CheckOutSoundBuffer();
  931.                                             } while (OutputBuffer == NIL);
  932.                                         OutputIndex = 0;
  933.                                     }
  934.                             }
  935.                     }
  936.                 SubmitBuffer((char*)OutputBuffer,OutputIndex / sizeof(short),NIL,NIL);
  937.             }
  938.          else
  939.             {
  940.                 for (Scan = NumTables - 1; Scan >= 0; Scan -= 1)
  941.                     {
  942.                         largefixedsigned*            Buffer = ReferenceArray[Scan];
  943.                         long                                    Index;
  944.  
  945.                         for (Index = 0; Index < NumberOfIterationsDecay; Index += 1)
  946.                             {
  947.                                 unsigned long                    SampleReference;
  948.                                 signed short                    Left;
  949.                                 signed short                    Right;
  950.                                 signed long                        Fraction;
  951.  
  952.                                 SampleReference = (WaveformIndex >> 16) & WaveformMask;
  953.                                 Left = Buffer[SampleReference] >> EIGHTBITSHIFTFACTOR;
  954.                                 Right = Buffer[SampleReference + 1] >> EIGHTBITSHIFTFACTOR;
  955.                                 Fraction = (WaveformIndex & 0xffff) / 2;
  956.                                 WaveformIndex += WaveformIncrementor;
  957.                                 ((char*)OutputBuffer)[OutputIndex] = (Left * (0x8000 - Fraction)
  958.                                     + Right * Fraction) >> 15;
  959.                                 OutputIndex += 1;
  960.                                 if (OutputIndex >= SOUNDBUFFERLENGTHBYTES / sizeof(char))
  961.                                     {
  962.                                         SubmitBuffer((char*)OutputBuffer,SOUNDBUFFERLENGTHBYTES
  963.                                             / sizeof(char),NIL,NIL);
  964.                                         if (RelinquishCPUJudiciouslyCheckCancel())
  965.                                             {
  966.                                                 goto EscapePoint;
  967.                                             }
  968.                                         do
  969.                                             {
  970.                                                 OutputBuffer = CheckOutSoundBuffer();
  971.                                             } while (OutputBuffer == NIL);
  972.                                         OutputIndex = 0;
  973.                                     }
  974.                             }
  975.                     }
  976.                 SubmitBuffer((char*)OutputBuffer,OutputIndex / sizeof(char),NIL,NIL);
  977.             }
  978.  
  979.      EscapePoint:
  980.         CloseSoundChannel(NIL,NIL);
  981.         ReleasePtr((char*)ReferenceArray);
  982.     }
  983.  
  984.  
  985. void                                WaveTableWindowDoMouseDown(OrdType XLoc, OrdType YLoc,
  986.                                             ModifierFlags Modifiers, WaveTableWindowRec* Window)
  987.     {
  988.         CheckPtrExistence(Window);
  989.         if ((XLoc >= GetWindowWidth(Window->ScreenID) - 15)
  990.             && (XLoc < GetWindowWidth(Window->ScreenID))
  991.             && (YLoc >= GetWindowHeight(Window->ScreenID) - 15)
  992.             && (YLoc < GetWindowHeight(Window->ScreenID)))
  993.             {
  994.                 UserGrowWindow(Window->ScreenID,XLoc,YLoc);
  995.                 WaveTableWindowJustResized(Window);
  996.             }
  997.         else if (TextEditHitTest(Window->NameEdit,XLoc,YLoc))
  998.             {
  999.                 if (Window->ActiveTextEdit != Window->NameEdit)
  1000.                     {
  1001.                         if (Window->ActiveTextEdit != NIL)
  1002.                             {
  1003.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1004.                             }
  1005.                         Window->ActiveTextEdit = Window->NameEdit;
  1006.                         EnableTextEditSelection(Window->NameEdit);
  1007.                     }
  1008.                 TextEditDoMouseDown(Window->NameEdit,XLoc,YLoc,Modifiers);
  1009.             }
  1010.         else if (TextEditHitTest(Window->FunctionEdit,XLoc,YLoc))
  1011.             {
  1012.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1013.                     {
  1014.                         if (Window->ActiveTextEdit != NIL)
  1015.                             {
  1016.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1017.                             }
  1018.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1019.                         EnableTextEditSelection(Window->FunctionEdit);
  1020.                     }
  1021.                 TextEditDoMouseDown(Window->FunctionEdit,XLoc,YLoc,Modifiers);
  1022.             }
  1023.         else if (TextEditHitTest(Window->TestAttackDuration,XLoc,YLoc))
  1024.             {
  1025.                 if (Window->ActiveTextEdit != Window->TestAttackDuration)
  1026.                     {
  1027.                         if (Window->ActiveTextEdit != NIL)
  1028.                             {
  1029.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1030.                             }
  1031.                         Window->ActiveTextEdit = Window->TestAttackDuration;
  1032.                         EnableTextEditSelection(Window->TestAttackDuration);
  1033.                     }
  1034.                 TextEditDoMouseDown(Window->TestAttackDuration,XLoc,YLoc,Modifiers);
  1035.             }
  1036.         else if (TextEditHitTest(Window->TestDecayDuration,XLoc,YLoc))
  1037.             {
  1038.                 if (Window->ActiveTextEdit != Window->TestDecayDuration)
  1039.                     {
  1040.                         if (Window->ActiveTextEdit != NIL)
  1041.                             {
  1042.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1043.                             }
  1044.                         Window->ActiveTextEdit = Window->TestDecayDuration;
  1045.                         EnableTextEditSelection(Window->TestDecayDuration);
  1046.                     }
  1047.                 TextEditDoMouseDown(Window->TestDecayDuration,XLoc,YLoc,Modifiers);
  1048.             }
  1049.         else if (TextEditHitTest(Window->TestFrequency,XLoc,YLoc))
  1050.             {
  1051.                 if (Window->ActiveTextEdit != Window->TestFrequency)
  1052.                     {
  1053.                         if (Window->ActiveTextEdit != NIL)
  1054.                             {
  1055.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1056.                             }
  1057.                         Window->ActiveTextEdit = Window->TestFrequency;
  1058.                         EnableTextEditSelection(Window->TestFrequency);
  1059.                     }
  1060.                 TextEditDoMouseDown(Window->TestFrequency,XLoc,YLoc,Modifiers);
  1061.             }
  1062.         else if (TextEditHitTest(Window->TestSamplingRate,XLoc,YLoc))
  1063.             {
  1064.                 if (Window->ActiveTextEdit != Window->TestSamplingRate)
  1065.                     {
  1066.                         if (Window->ActiveTextEdit != NIL)
  1067.                             {
  1068.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1069.                             }
  1070.                         Window->ActiveTextEdit = Window->TestSamplingRate;
  1071.                         EnableTextEditSelection(Window->TestSamplingRate);
  1072.                     }
  1073.                 TextEditDoMouseDown(Window->TestSamplingRate,XLoc,YLoc,Modifiers);
  1074.             }
  1075.         else if (TextEditHitTest(Window->NumFramesEdit,XLoc,YLoc))
  1076.             {
  1077.                 WaveTableWindowSetNewNumFrames(Window);
  1078.             }
  1079.         else if (TextEditHitTest(Window->NumTablesEdit,XLoc,YLoc))
  1080.             {
  1081.                 WaveTableWindowSetNewNumTables(Window);
  1082.             }
  1083.         else if (IconButtonHitTest(Window->Bits8Button,XLoc,YLoc))
  1084.             {
  1085.                 if (IconButtonMouseDown(Window->Bits8Button,XLoc,YLoc,NIL,NIL))
  1086.                     {
  1087.                         SetWaveTableStorDispNumBits(Window->WaveTableData,eSample8bit);
  1088.                         SetIconButtonState(Window->Bits16Button,False);
  1089.                         Window->WaveDataModified = True;
  1090.                     }
  1091.             }
  1092.         else if (IconButtonHitTest(Window->Bits16Button,XLoc,YLoc))
  1093.             {
  1094.                 if (IconButtonMouseDown(Window->Bits16Button,XLoc,YLoc,NIL,NIL))
  1095.                     {
  1096.                         SetWaveTableStorDispNumBits(Window->WaveTableData,eSample16bit);
  1097.                         SetIconButtonState(Window->Bits8Button,False);
  1098.                         Window->WaveDataModified = True;
  1099.                     }
  1100.             }
  1101.         else if (ScrollHitTest(Window->TableScroll,XLoc,YLoc))
  1102.             {
  1103.                 ScrollHitProc(Window->TableScroll,CheckModifiers(),XLoc,YLoc,Window,
  1104.                     (void (*)(long,ScrollType,void*))&WaveTableWindowScrollHook);
  1105.             }
  1106.         else if (SimpleButtonHitTest(Window->TestButton,XLoc,YLoc))
  1107.             {
  1108.                 if (SimpleButtonMouseDown(Window->TestButton,XLoc,YLoc,NIL,NIL))
  1109.                     {
  1110.                         WaveTablePlayIt(Window);
  1111.                     }
  1112.             }
  1113.         else
  1114.             {
  1115.                 if (Window->ActiveTextEdit != NIL)
  1116.                     {
  1117.                         DisableTextEditSelection(Window->ActiveTextEdit);
  1118.                         Window->ActiveTextEdit = NIL;
  1119.                     }
  1120.             }
  1121.     }
  1122.  
  1123.  
  1124. void                                WaveTableWindowDoKeyDown(unsigned char KeyCode,
  1125.                                             ModifierFlags Modifiers, WaveTableWindowRec* Window)
  1126.     {
  1127.         CheckPtrExistence(Window);
  1128.         if (Window->ActiveTextEdit != NIL)
  1129.             {
  1130.                 TextEditDoKeyPressed(Window->ActiveTextEdit,KeyCode,Modifiers);
  1131.             }
  1132.     }
  1133.  
  1134.  
  1135. void                                WaveTableWindowClose(WaveTableWindowRec* Window)
  1136.     {
  1137.         CheckPtrExistence(Window);
  1138.         DisposeWaveTableWindow(Window);
  1139.     }
  1140.  
  1141.  
  1142. void                                WaveTableWindowUpdator(WaveTableWindowRec* Window)
  1143.     {
  1144.         OrdType                        Height;
  1145.         OrdType                        Width;
  1146.  
  1147.         CheckPtrExistence(Window);
  1148.         Width = GetWindowWidth(Window->ScreenID);
  1149.         Height = GetWindowHeight(Window->ScreenID);
  1150.  
  1151.         TextEditFullRedraw(Window->NameEdit);
  1152.         TextEditFullRedraw(Window->FunctionEdit);
  1153.         TextEditFullRedraw(Window->NumFramesEdit);
  1154.         TextEditFullRedraw(Window->NumTablesEdit);
  1155.         TextEditFullRedraw(Window->TestAttackDuration);
  1156.         TextEditFullRedraw(Window->TestDecayDuration);
  1157.         TextEditFullRedraw(Window->TestFrequency);
  1158.         TextEditFullRedraw(Window->TestSamplingRate);
  1159.         RedrawSimpleButton(Window->TestButton);
  1160.         RedrawIconButton(Window->Bits8Button);
  1161.         RedrawIconButton(Window->Bits16Button);
  1162.         RedrawScrollBar(Window->TableScroll);
  1163.         WaveTableWindowRedrawTable(Window);
  1164.  
  1165.         SetClipRect(Window->ScreenID,0,0,Width,Height);
  1166.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Name:",5,NAMEX,NAMEY,ePlain);
  1167.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Frames:",7,FRAMEX,FRAMEY,ePlain);
  1168.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Tables:",7,TABLESX,TABLESY,ePlain);
  1169.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Attack:",12,
  1170.             TESTATTACKX,TESTATTACKY,ePlain);
  1171.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Decay:",11,
  1172.             TESTDECAYX,TESTDECAYY,ePlain);
  1173.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Freq:",10,
  1174.             TESTFREQX,TESTFREQY,ePlain);
  1175.         DrawTextLine(Window->ScreenID,GetScreenFont(),9,"Test Smpl Rate:",15,
  1176.             TESTSAMPLX,TESTSAMPLY,ePlain);
  1177.  
  1178.         SetClipRect(Window->ScreenID,Width - 15,Height - 15,Width,Height);
  1179.         DrawBitmap(Window->ScreenID,Width - 15,Height - 15,
  1180.             GetGrowIcon(Window->MyGenericWindow == GetCurrentWindowID()));
  1181.     }
  1182.  
  1183.  
  1184. void                                WaveTableWindowMenuSetup(WaveTableWindowRec* Window)
  1185.     {
  1186.         CheckPtrExistence(Window);
  1187.         MainWindowEnableGlobalMenus(Window->MainWindow);
  1188.         EnableMenuItem(mPaste);
  1189.         ChangeItemName(mPaste,"Paste Text");
  1190.         if (Window->ActiveTextEdit != NIL)
  1191.             {
  1192.                 if (TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1193.                     {
  1194.                         EnableMenuItem(mCut);
  1195.                         ChangeItemName(mCut,"Cut Text");
  1196.                         EnableMenuItem(mCopy);
  1197.                         ChangeItemName(mCopy,"Copy Text");
  1198.                         EnableMenuItem(mClear);
  1199.                         ChangeItemName(mClear,"Clear Text");
  1200.                     }
  1201.                 EnableMenuItem(mSelectAll);
  1202.                 ChangeItemName(mSelectAll,"Select All Text");
  1203.                 if (TextEditCanWeUndo(Window->ActiveTextEdit))
  1204.                     {
  1205.                         EnableMenuItem(mUndo);
  1206.                         ChangeItemName(mUndo,"Undo Text Change");
  1207.                     }
  1208.             }
  1209.          else
  1210.             {
  1211.                 if (Window->UndoBackupWaveTable != NIL)
  1212.                     {
  1213.                         EnableMenuItem(mUndo);
  1214.                         ChangeItemName(mUndo,"Undo Wave Table Edit");
  1215.                     }
  1216.             }
  1217.         EnableMenuItem(mCloseFile);
  1218.         ChangeItemName(mCloseFile,"Close Wave Table Editor");
  1219.         EnableMenuItem(mEvaluateCalc);
  1220.         EnableMenuItem(mShiftLeft);
  1221.         EnableMenuItem(mShiftRight);
  1222.         EnableMenuItem(mBalanceParens);
  1223.         ChangeItemName(mDeleteObject,"Delete Wave Table");
  1224.         EnableMenuItem(mDeleteObject);
  1225.         EnableMenuItem(mFind);
  1226.         if (PtrSize(GlobalSearchString) != 0)
  1227.             {
  1228.                 EnableMenuItem(mFindAgain);
  1229.                 if ((Window->ActiveTextEdit != NIL)
  1230.                     && TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1231.                     {
  1232.                         EnableMenuItem(mReplace);
  1233.                         EnableMenuItem(mReplaceAndFindAgain);
  1234.                     }
  1235.             }
  1236.         if ((Window->ActiveTextEdit != NIL)
  1237.             && TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1238.             {
  1239.                 EnableMenuItem(mEnterSelection);
  1240.             }
  1241.         SetItemCheckmark(Window->MyMenuItem);
  1242.     }
  1243.  
  1244.  
  1245. void                                WaveTableWindowDoMenuCommand(WaveTableWindowRec* Window,
  1246.                                             MenuItemType* MenuItem)
  1247.     {
  1248.         CheckPtrExistence(Window);
  1249.         if (MainWindowDoGlobalMenuItem(Window->MainWindow,MenuItem))
  1250.             {
  1251.             }
  1252.         else if (MenuItem == mPaste)
  1253.             {
  1254.                 if (Window->ActiveTextEdit != NIL)
  1255.                     {
  1256.                         TextEditDoMenuPaste(Window->ActiveTextEdit);
  1257.                     }
  1258.             }
  1259.         else if (MenuItem == mCut)
  1260.             {
  1261.                 if (Window->ActiveTextEdit != NIL)
  1262.                     {
  1263.                         TextEditDoMenuCut(Window->ActiveTextEdit);
  1264.                     }
  1265.             }
  1266.         else if (MenuItem == mCopy)
  1267.             {
  1268.                 if (Window->ActiveTextEdit != NIL)
  1269.                     {
  1270.                         TextEditDoMenuCopy(Window->ActiveTextEdit);
  1271.                     }
  1272.             }
  1273.         else if (MenuItem == mClear)
  1274.             {
  1275.                 if (Window->ActiveTextEdit != NIL)
  1276.                     {
  1277.                         TextEditDoMenuClear(Window->ActiveTextEdit);
  1278.                     }
  1279.             }
  1280.         else if (MenuItem == mSelectAll)
  1281.             {
  1282.                 if (Window->ActiveTextEdit != NIL)
  1283.                     {
  1284.                         TextEditDoMenuSelectAll(Window->ActiveTextEdit);
  1285.                     }
  1286.             }
  1287.         else if (MenuItem == mUndo)
  1288.             {
  1289.                 if (Window->ActiveTextEdit != NIL)
  1290.                     {
  1291.                         TextEditDoMenuUndo(Window->ActiveTextEdit);
  1292.                     }
  1293.                  else
  1294.                     {
  1295.                         WaveTableStorDispRec*        Temp;
  1296.  
  1297.                         Temp = Window->UndoBackupWaveTable;
  1298.                         Window->UndoBackupWaveTable = Window->WaveTableData;
  1299.                         Window->WaveTableData = Temp;
  1300.                         Window->WaveDataModified = True;
  1301.                         WaveTableWindowUpdateAllParameters(Window);
  1302.                     }
  1303.             }
  1304.         else if (MenuItem == mCloseFile)
  1305.             {
  1306.                 WaveTableWindowClose(Window);
  1307.             }
  1308.         else if (MenuItem == mEvaluateCalc)
  1309.             {
  1310.                 WaveTableWindowEvaluateFunction(Window);
  1311.             }
  1312.         else if (MenuItem == mShiftLeft)
  1313.             {
  1314.                 TextEditShiftSelectionLeftOneTab(Window->ActiveTextEdit);
  1315.             }
  1316.         else if (MenuItem == mShiftRight)
  1317.             {
  1318.                 TextEditShiftSelectionRightOneTab(Window->ActiveTextEdit);
  1319.             }
  1320.         else if (MenuItem == mBalanceParens)
  1321.             {
  1322.                 TextEditBalanceParens(Window->ActiveTextEdit);
  1323.             }
  1324.         else if (MenuItem == mDeleteObject)
  1325.             {
  1326.                 WaveTableListDeleteWaveTable(Window->WaveTableList,Window->WaveTableObject);
  1327.             }
  1328.         else if (MenuItem == mFind)
  1329.             {
  1330.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1331.                     {
  1332.                         if (Window->ActiveTextEdit != NIL)
  1333.                             {
  1334.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1335.                             }
  1336.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1337.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1338.                     }
  1339.                 switch (DoFindDialog(&GlobalSearchString,&GlobalReplaceString,
  1340.                     mCut,mPaste,mCopy,mUndo,mSelectAll,mClear))
  1341.                     {
  1342.                         default:
  1343.                             EXECUTE(PRERR(ForceAbort,
  1344.                                 "WaveTableWindowDoMenuCommand:  bad value from DoFindDialog"));
  1345.                             break;
  1346.                         case eFindCancel:
  1347.                         case eDontFind:
  1348.                             break;
  1349.                         case eFindFromStart:
  1350.                             SetTextEditInsertionPoint(Window->ActiveTextEdit,0,0);
  1351.                             TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1352.                             TextEditShowSelection(Window->ActiveTextEdit);
  1353.                             break;
  1354.                         case eFindAgain:
  1355.                             TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1356.                             TextEditShowSelection(Window->ActiveTextEdit);
  1357.                             break;
  1358.                     }
  1359.             }
  1360.         else if (MenuItem == mFindAgain)
  1361.             {
  1362.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1363.                     {
  1364.                         if (Window->ActiveTextEdit != NIL)
  1365.                             {
  1366.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1367.                             }
  1368.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1369.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1370.                     }
  1371.                 TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1372.                 TextEditShowSelection(Window->ActiveTextEdit);
  1373.             }
  1374.         else if (MenuItem == mReplace)
  1375.             {
  1376.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1377.                     {
  1378.                         if (Window->ActiveTextEdit != NIL)
  1379.                             {
  1380.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1381.                             }
  1382.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1383.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1384.                     }
  1385.                 if (TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1386.                     {
  1387.                         TextEditInsertRawDataWithUndo(Window->ActiveTextEdit,GlobalReplaceString,
  1388.                             SYSTEMLINEFEED);
  1389.                     }
  1390.             }
  1391.         else if (MenuItem == mReplaceAndFindAgain)
  1392.             {
  1393.                 if (Window->ActiveTextEdit != Window->FunctionEdit)
  1394.                     {
  1395.                         if (Window->ActiveTextEdit != NIL)
  1396.                             {
  1397.                                 DisableTextEditSelection(Window->ActiveTextEdit);
  1398.                             }
  1399.                         Window->ActiveTextEdit = Window->FunctionEdit;
  1400.                         EnableTextEditSelection(Window->ActiveTextEdit);
  1401.                     }
  1402.                 if (TextEditIsThereValidSelection(Window->ActiveTextEdit))
  1403.                     {
  1404.                         TextEditInsertRawDataWithUndo(Window->ActiveTextEdit,GlobalReplaceString,
  1405.                             SYSTEMLINEFEED);
  1406.                         TextEditFindAgain(Window->ActiveTextEdit,GlobalSearchString);
  1407.                         TextEditShowSelection(Window->ActiveTextEdit);
  1408.                     }
  1409.             }
  1410.         else if (MenuItem == mEnterSelection)
  1411.             {
  1412.                 if (Window->ActiveTextEdit != NIL)
  1413.                     {
  1414.                         char*                        NewString;
  1415.  
  1416.                         NewString = TextEditGetSelection(Window->ActiveTextEdit);
  1417.                         if (NewString != NIL)
  1418.                             {
  1419.                                 ReleasePtr(GlobalSearchString);
  1420.                                 GlobalSearchString = NewString;
  1421.                             }
  1422.                     }
  1423.             }
  1424.         else
  1425.             {
  1426.                 EXECUTE(PRERR(AllowResume,"WaveTableWindowDoMenuCommand:  unknown menu command"));
  1427.             }
  1428.     }
  1429.  
  1430.  
  1431. /* get a copy of the wave table's name */
  1432. char*                                WaveTableWindowGetNameCopy(WaveTableWindowRec* Window)
  1433.     {
  1434.         char*                            TextCopy;
  1435.  
  1436.         CheckPtrExistence(Window);
  1437.         TextCopy = TextEditGetRawData(Window->NameEdit,"\x0a");
  1438.         if (TextCopy != NIL)
  1439.             {
  1440.                 SetTag(TextCopy,"WaveTableWindowNameCopy");
  1441.             }
  1442.         return TextCopy;
  1443.     }
  1444.  
  1445.  
  1446. /* get a copy of the wave table's formula */
  1447. char*                                WaveTableWindowGetFormulaCopy(WaveTableWindowRec* Window)
  1448.     {
  1449.         char*                            TextCopy;
  1450.  
  1451.         CheckPtrExistence(Window);
  1452.         TextCopy = TextEditGetRawData(Window->FunctionEdit,"\x0a");
  1453.         if (TextCopy != NIL)
  1454.             {
  1455.                 SetTag(TextCopy,"WaveTableWindowFormulaCopy");
  1456.             }
  1457.         return TextCopy;
  1458.     }
  1459.  
  1460.  
  1461. /* get the number of bits used for the wave table */
  1462. NumBitsType                    WaveTableWindowGetNumBits(WaveTableWindowRec* Window)
  1463.     {
  1464.         CheckPtrExistence(Window);
  1465.         if (GetIconButtonState(Window->Bits16Button))
  1466.             {
  1467.                 return eSample16bit;
  1468.             }
  1469.          else
  1470.             {
  1471.                 return eSample8bit;
  1472.             }
  1473.     }
  1474.  
  1475.  
  1476. /* get the number of periods in the wave table */
  1477. long                                WaveTableWindowGetNumTables(WaveTableWindowRec* Window)
  1478.     {
  1479.         CheckPtrExistence(Window);
  1480.         return WaveTableStorDispNumTables(Window->WaveTableData);
  1481.     }
  1482.  
  1483.  
  1484. /* get the number of frames in each period of the wave table */
  1485. long                                WaveTableWindowGetNumFramesPerTable(WaveTableWindowRec* Window)
  1486.     {
  1487.         CheckPtrExistence(Window);
  1488.         return WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  1489.     }
  1490.  
  1491.  
  1492. /* get the pitch at which the wave table should be tested */
  1493. double                            WaveTableWindowGetPitch(WaveTableWindowRec* Window)
  1494.     {
  1495.         char*                            Text;
  1496.         double                        ReturnValue;
  1497.  
  1498.         CheckPtrExistence(Window);
  1499.         Text = TextEditGetRawData(Window->TestFrequency,SYSTEMLINEFEED);
  1500.         if (Text != NIL)
  1501.             {
  1502.                 ReturnValue = StringToLongDouble(Text,PtrSize(Text));
  1503.                 ReleasePtr(Text);
  1504.             }
  1505.          else
  1506.             {
  1507.                 ReturnValue = 261.625565300598635;
  1508.             }
  1509.         return ReturnValue;
  1510.     }
  1511.  
  1512.  
  1513. /* get the duration (seconds) for the increasing table index phase of the test */
  1514. double                            WaveTableWindowGetAscendingDuration(WaveTableWindowRec* Window)
  1515.     {
  1516.         char*                            Text;
  1517.         double                        ReturnValue;
  1518.  
  1519.         CheckPtrExistence(Window);
  1520.         Text = TextEditGetRawData(Window->TestAttackDuration,SYSTEMLINEFEED);
  1521.         if (Text != NIL)
  1522.             {
  1523.                 ReturnValue = StringToLongDouble(Text,PtrSize(Text));
  1524.                 ReleasePtr(Text);
  1525.             }
  1526.          else
  1527.             {
  1528.                 ReturnValue = 1;
  1529.             }
  1530.         return ReturnValue;
  1531.     }
  1532.  
  1533.  
  1534. /* get the duration (seconds) for the decreasing table index phase of the test */
  1535. double                            WaveTableWindowGetDescendingDuration(WaveTableWindowRec* Window)
  1536.     {
  1537.         char*                            Text;
  1538.         double                        ReturnValue;
  1539.  
  1540.         CheckPtrExistence(Window);
  1541.         Text = TextEditGetRawData(Window->TestDecayDuration,SYSTEMLINEFEED);
  1542.         if (Text != NIL)
  1543.             {
  1544.                 ReturnValue = StringToLongDouble(Text,PtrSize(Text));
  1545.                 ReleasePtr(Text);
  1546.             }
  1547.          else
  1548.             {
  1549.                 ReturnValue = 2;
  1550.             }
  1551.         return ReturnValue;
  1552.     }
  1553.  
  1554.  
  1555. /* get the sampling rate to use for the test */
  1556. long                                WaveTableWindowGetTestSamplingRate(WaveTableWindowRec* Window)
  1557.     {
  1558.         char*                            Text;
  1559.         double                        ReturnValue;
  1560.  
  1561.         CheckPtrExistence(Window);
  1562.         Text = TextEditGetRawData(Window->TestSamplingRate,SYSTEMLINEFEED);
  1563.         if (Text != NIL)
  1564.             {
  1565.                 ReturnValue = StringToInteger(Text,PtrSize(Text));
  1566.                 ReleasePtr(Text);
  1567.             }
  1568.          else
  1569.             {
  1570.                 ReturnValue = 44100;
  1571.             }
  1572.         return ReturnValue;
  1573.     }
  1574.  
  1575.  
  1576. /* reset the scroll bar indices and redraw it */
  1577. void                                WaveTableWindowUpdateScrollBar(WaveTableWindowRec* Window)
  1578.     {
  1579.         CheckPtrExistence(Window);
  1580.         SetMaxScrollIndex(Window->TableScroll,WaveTableWindowGetNumTables(Window));
  1581.         SetScrollIndex(Window->TableScroll,Window->CurrentlyVisibleTable);
  1582.     }
  1583.  
  1584.  
  1585. /* redraw the wave table waveform box */
  1586. void                                WaveTableWindowRedrawTable(WaveTableWindowRec* Window)
  1587.     {
  1588.         OrdType                        WindowWidth;
  1589.         OrdType                        WindowHeight;
  1590.         long                            Scan;
  1591.         long                            Limit;
  1592.         OrdType                        PreviousYValue;
  1593.         OrdType                        PreviousXValue;
  1594.         MyBoolean                    PreviousYValueIsValid;
  1595.  
  1596.         CheckPtrExistence(Window);
  1597.         WindowWidth = GetWindowWidth(Window->ScreenID);
  1598.         WindowHeight = GetWindowHeight(Window->ScreenID);
  1599.         SetClipRect(Window->ScreenID,WAVEFORMVIEWX,WAVEFORMVIEWY,
  1600.             WAVEFORMVIEWWIDTH(WindowWidth),WAVEFORMVIEWHEIGHT(WindowHeight));
  1601.         DrawBoxFrame(Window->ScreenID,eBlack,WAVEFORMVIEWX,WAVEFORMVIEWY,
  1602.             WAVEFORMVIEWWIDTH(WindowWidth),WAVEFORMVIEWHEIGHT(WindowHeight));
  1603.         if (WaveTableWindowGetNumTables(Window) == 0)
  1604.             {
  1605.                 DrawBoxPaint(Window->ScreenID,eLightGrey,WAVEFORMVIEWX + 1,WAVEFORMVIEWY + 1,
  1606.                     WAVEFORMVIEWWIDTH(WindowWidth) - 2,WAVEFORMVIEWHEIGHT(WindowHeight) - 2);
  1607.                 return;
  1608.             }
  1609.         DrawBoxErase(Window->ScreenID,WAVEFORMVIEWX + 1,WAVEFORMVIEWY + 1,
  1610.             WAVEFORMVIEWWIDTH(WindowWidth) - 2,WAVEFORMVIEWHEIGHT(WindowHeight) - 2);
  1611.         ERROR((Window->CurrentlyVisibleTable < 0) || (Window->CurrentlyVisibleTable
  1612.             >= WaveTableWindowGetNumTables(Window)),PRERR(ForceAbort,
  1613.             "WaveTableWindowRedrawTable:  current table index is out of range"));
  1614.         Limit = WaveTableWindowGetNumFramesPerTable(Window);
  1615.         PreviousYValueIsValid = False;
  1616.         for (Scan = 0; Scan < Limit; Scan += 1)
  1617.             {
  1618.                 double                    Value;
  1619.                 OrdType                    ThisYValue;
  1620.                 OrdType                    ThisXValue;
  1621.  
  1622.                 Value = largefixed2double(WaveTableStorDispGetFrame(Window->WaveTableData,
  1623.                     Window->CurrentlyVisibleTable,Scan));
  1624.                 ThisYValue = (1 - ((Value + 1) / 2)) * (WAVEFORMVIEWHEIGHT(WindowHeight) - 3)
  1625.                     + WAVEFORMVIEWY + 1;
  1626.                 ThisXValue = (Scan * (WAVEFORMVIEWWIDTH(WindowWidth) - 2))
  1627.                     / (Limit - 1) + WAVEFORMVIEWX + 1;
  1628.                 if (!PreviousYValueIsValid)
  1629.                     {
  1630.                         PreviousYValueIsValid = True;
  1631.                         PreviousYValue = ThisYValue;
  1632.                         PreviousXValue = ThisXValue;
  1633.                     }
  1634.                 DrawLine(Window->ScreenID,eBlack,PreviousXValue,PreviousYValue,
  1635.                     ThisXValue - PreviousXValue,ThisYValue - PreviousYValue);
  1636.                 PreviousYValue = ThisYValue;
  1637.                 PreviousXValue = ThisXValue;
  1638.             }
  1639.     }
  1640.  
  1641.  
  1642. /* the name of the file has changed, so change the title bar.  the string is a */
  1643. /* non-null-terminated, and the caller is responsible for disposing of it */
  1644. void                                WaveTableWindowGlobalNameChange(WaveTableWindowRec* Window,
  1645.                                             char* NewFilename)
  1646.     {
  1647.         char*                            LocalNameCopy;
  1648.  
  1649.         CheckPtrExistence(Window);
  1650.         CheckPtrExistence(NewFilename);
  1651.         LocalNameCopy = WaveTableWindowGetNameCopy(Window);
  1652.         if (LocalNameCopy != NIL)
  1653.             {
  1654.                 char*                            SeparatorString;
  1655.  
  1656.                 SeparatorString = StringToBlockCopy(":  ");
  1657.                 if (SeparatorString != NIL)
  1658.                     {
  1659.                         char*                            LeftHalfOfString;
  1660.  
  1661.                         LeftHalfOfString = ConcatBlockCopy(NewFilename,SeparatorString);
  1662.                         if (LeftHalfOfString != NIL)
  1663.                             {
  1664.                                 char*                            TotalString;
  1665.  
  1666.                                 TotalString = ConcatBlockCopy(LeftHalfOfString,LocalNameCopy);
  1667.                                 if (TotalString != NIL)
  1668.                                     {
  1669.                                         char*                            NullTerminatedString;
  1670.  
  1671.                                         NullTerminatedString = BlockToStringCopy(TotalString);
  1672.                                         if (NullTerminatedString != NIL)
  1673.                                             {
  1674.                                                 SetWindowName(Window->ScreenID,NullTerminatedString);
  1675.                                                 ChangeItemName(Window->MyMenuItem,NullTerminatedString);
  1676.                                                 ReleasePtr(NullTerminatedString);
  1677.                                             }
  1678.                                         ReleasePtr(TotalString);
  1679.                                     }
  1680.                                 ReleasePtr(LeftHalfOfString);
  1681.                             }
  1682.                         ReleasePtr(SeparatorString);
  1683.                     }
  1684.                 ReleasePtr(LocalNameCopy);
  1685.             }
  1686.     }
  1687.  
  1688.  
  1689. /* reset the title bar name even if the document name hasn't changed */
  1690. void                                WaveTableWindowResetTitlebar(WaveTableWindowRec* Window)
  1691.     {
  1692.         char*                            DocumentName;
  1693.  
  1694.         CheckPtrExistence(Window);
  1695.         DocumentName = GetCopyOfDocumentName(Window->MainWindow);
  1696.         if (DocumentName != NIL)
  1697.             {
  1698.                 WaveTableWindowGlobalNameChange(Window,DocumentName);
  1699.                 ReleasePtr(DocumentName);
  1700.             }
  1701.     }
  1702.  
  1703.  
  1704. /* set the number of periods to that stored in the edit box, and interpolate */
  1705. /* the periods. */
  1706. void                                WaveTableWindowSetNewNumTables(WaveTableWindowRec* Window)
  1707.     {
  1708.         long                            OriginalNumTables;
  1709.         long                            NewNumTables;
  1710.  
  1711.         CheckPtrExistence(Window);
  1712.         OriginalNumTables = WaveTableWindowGetNumTables(Window);
  1713.         NewNumTables = DoNumberDialog("Enter new number of tables:",OriginalNumTables,
  1714.             mCut,mPaste,mCopy,mUndo,mSelectAll,mClear);
  1715.         if (NewNumTables != OriginalNumTables)
  1716.             {
  1717.                 WaveTableStorDispRec*    NewTable;
  1718.                 long                                    TableScan;
  1719.  
  1720.                 /* free up undo-backup info */
  1721.                 if (Window->UndoBackupWaveTable != NIL)
  1722.                     {
  1723.                         DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  1724.                         Window->UndoBackupWaveTable = NIL;
  1725.                     }
  1726.  
  1727.                 /* build new table */
  1728.                 NewTable = NewWaveTableStorDisp(WaveTableStorDispNumBits(Window->WaveTableData),
  1729.                     WaveTableStorDispNumFramesPerTable(Window->WaveTableData));
  1730.                 if (NewTable == NIL)
  1731.                     {
  1732.                      MemoryFailurePoint1:
  1733.                         AlertHalt("There is not enough memory available to resize the wave table.",NIL);
  1734.                         return;
  1735.                     }
  1736.                 for (TableScan = 0; TableScan < NewNumTables; TableScan += 1)
  1737.                     {
  1738.                         if (!WaveTableStorDispAppendEntry(NewTable))
  1739.                             {
  1740.                              MemoryFailurePoint2:
  1741.                                 DisposeWaveTableStorDisp(NewTable);
  1742.                                 goto MemoryFailurePoint1;
  1743.                             }
  1744.                     }
  1745.  
  1746.                 if ((NewNumTables != 0) && (OriginalNumTables != 0))
  1747.                     {
  1748.                         long                        NumFrames;
  1749.  
  1750.                         NumFrames = WaveTableStorDispNumFramesPerTable(NewTable);
  1751.                         /* store the neat things into the table.  we use linear interpolation */
  1752.                         /* between adjacent tables to create new tables. */
  1753.                         for (TableScan = 0; TableScan < NewNumTables; TableScan += 1)
  1754.                             {
  1755.                                 double                        LeftWeight;
  1756.                                 double                        RightWeight;
  1757.                                 long                            LeftIndex;
  1758.                                 long                            RightIndex;
  1759.                                 double                        PrecisePositioning;
  1760.                                 long                            FrameScan;
  1761.  
  1762.                                 if (NewNumTables > 1)
  1763.                                     {
  1764.                                         PrecisePositioning = (double)TableScan / (double)(NewNumTables - 1)
  1765.                                             * (double)(OriginalNumTables - 1);
  1766.                                     }
  1767.                                  else
  1768.                                     {
  1769.                                         PrecisePositioning = (double)(OriginalNumTables - 1) / 2;
  1770.                                     }
  1771.                                 LeftIndex = (long)PrecisePositioning;
  1772.                                 RightIndex = LeftIndex + 1;
  1773.                                 RightWeight = PrecisePositioning - LeftIndex;
  1774.                                 LeftWeight = 1 - RightWeight;
  1775.                                 for (FrameScan = 0; FrameScan < NumFrames; FrameScan += 1)
  1776.                                     {
  1777.                                         double                        LeftValue;
  1778.                                         double                        RightValue;
  1779.                                         double                        ResultantComposite;
  1780.  
  1781.                                         LeftValue = largefixed2double(WaveTableStorDispGetFrame(
  1782.                                             Window->WaveTableData,LeftIndex,FrameScan));
  1783.                                         if (RightIndex < OriginalNumTables)
  1784.                                             {
  1785.                                                 RightValue = largefixed2double(WaveTableStorDispGetFrame(
  1786.                                                     Window->WaveTableData,RightIndex,FrameScan));
  1787.                                             }
  1788.                                          else
  1789.                                             {
  1790.                                                 RightValue = 0;
  1791.                                                 ERROR(RightWeight != 0,PRERR(ForceAbort,
  1792.                                                     "WaveTableWindowSetNewNumTables:  on last table, but right "
  1793.                                                     "weight is non-zero."));
  1794.                                             }
  1795.                                         ResultantComposite = LeftValue * LeftWeight
  1796.                                             + RightValue * RightWeight;
  1797.                                         WaveTableStorDispSetFrame(NewTable,TableScan,FrameScan,
  1798.                                             double2largefixed(ResultantComposite));
  1799.                                     }
  1800.                             }
  1801.                     }
  1802.  
  1803.                 /* save it */
  1804.                 Window->UndoBackupWaveTable = Window->WaveTableData;
  1805.                 Window->WaveTableData = NewTable;
  1806.                 WaveTableWindowUpdateAllParameters(Window);
  1807.                 Window->WaveDataModified = True;
  1808.             }
  1809.     }
  1810.  
  1811.  
  1812. /* set the number of periods edit box to be the same as the data */
  1813. void                                WaveTableWindowUpdateTableCountEdit(WaveTableWindowRec* Window)
  1814.     {
  1815.         char*                            StringTemp;
  1816.  
  1817.         CheckPtrExistence(Window);
  1818.         StringTemp = IntegerToString(WaveTableObjectGetNumTables(Window->WaveTableObject));
  1819.         if (StringTemp == NIL)
  1820.             {
  1821.                 return;
  1822.             }
  1823.         TextEditNewRawData(Window->NumTablesEdit,StringTemp,"\x0a");
  1824.         ReleasePtr(StringTemp);
  1825.         TextEditHasBeenSaved(Window->NumTablesEdit);
  1826.     }
  1827.  
  1828.  
  1829. /* set the number of frames edit box to be the same as the data */
  1830. void                                WaveTableWindowUpdateFrameCountEdit(WaveTableWindowRec* Window)
  1831.     {
  1832.         char*                            StringTemp;
  1833.  
  1834.         CheckPtrExistence(Window);
  1835.         StringTemp = IntegerToString(
  1836.             WaveTableStorDispNumFramesPerTable(Window->WaveTableData));
  1837.         if (StringTemp == NIL)
  1838.             {
  1839.                 return;
  1840.             }
  1841.         TextEditNewRawData(Window->NumFramesEdit,StringTemp,"\x0a");
  1842.         ReleasePtr(StringTemp);
  1843.         TextEditHasBeenSaved(Window->NumFramesEdit);
  1844.     }
  1845.  
  1846.  
  1847. /* set all edit boxes to be the same as the underlying data */
  1848. void                                WaveTableWindowUpdateAllParameters(WaveTableWindowRec* Window)
  1849.     {
  1850.         if (Window->CurrentlyVisibleTable
  1851.             > WaveTableObjectGetNumTables(Window->WaveTableObject) - 1)
  1852.             {
  1853.                 Window->CurrentlyVisibleTable
  1854.                     = WaveTableObjectGetNumTables(Window->WaveTableObject) - 1;
  1855.             }
  1856.         if (Window->CurrentlyVisibleTable < 0)
  1857.             {
  1858.                 Window->CurrentlyVisibleTable = 0;
  1859.             }
  1860.         WaveTableWindowUpdateTableCountEdit(Window);
  1861.         WaveTableWindowUpdateFrameCountEdit(Window);
  1862.         WaveTableWindowUpdateScrollBar(Window);
  1863.         WaveTableWindowRedrawTable(Window);
  1864.     }
  1865.  
  1866.  
  1867. /* give a dialog box asking for a new number of frames, and then interpolate all */
  1868. /* of the wave periods. */
  1869. void                                WaveTableWindowSetNewNumFrames(WaveTableWindowRec* Window)
  1870.     {
  1871.         long                            OriginalNumFrames;
  1872.         long                            NewNumFrames;
  1873.         WaveTableStorDispRec*    NewTable;
  1874.         long                            NumberOfTables;
  1875.         long                            TableScan;
  1876.  
  1877.         CheckPtrExistence(Window);
  1878.         OriginalNumFrames = WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  1879.         NewNumFrames = AskForNewWaveTableSize(OriginalNumFrames);
  1880.  
  1881.         if (NewNumFrames == OriginalNumFrames)
  1882.             {
  1883.                 return;
  1884.             }
  1885.  
  1886.         /* dump the undo backup information */
  1887.         if (Window->UndoBackupWaveTable != NIL)
  1888.             {
  1889.                 DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  1890.                 Window->UndoBackupWaveTable = NIL;
  1891.             }
  1892.  
  1893.         /* create a new table */
  1894.         NewTable = NewWaveTableStorDisp(WaveTableStorDispNumBits(Window->WaveTableData),
  1895.             NewNumFrames);
  1896.         if (NewTable == NIL)
  1897.             {
  1898.              MemoryFailurePoint1:
  1899.                 AlertHalt("There is not enough memory available to resample the wave table.",NIL);
  1900.                 return;
  1901.             }
  1902.         NumberOfTables = WaveTableStorDispNumTables(Window->WaveTableData);
  1903.         for (TableScan = 0; TableScan < NumberOfTables; TableScan += 1)
  1904.             {
  1905.                 if (!WaveTableStorDispAppendEntry(NewTable))
  1906.                     {
  1907.                      MemoryFailurePoint2:
  1908.                         DisposeWaveTableStorDisp(NewTable);
  1909.                         goto MemoryFailurePoint1;
  1910.                     }
  1911.             }
  1912.  
  1913.         /* this one handles interpolating between entries to expand the table */
  1914.         if (NewNumFrames > OriginalNumFrames)
  1915.             {
  1916.                 long                            ExpansionFactor;
  1917.  
  1918.                 ExpansionFactor = NewNumFrames / OriginalNumFrames;
  1919.                 for (TableScan = 0; TableScan < NumberOfTables; TableScan += 1)
  1920.                     {
  1921.                         long                            NewFrameScan;
  1922.  
  1923.                         for (NewFrameScan = 0; NewFrameScan < NewNumFrames; NewFrameScan += 1)
  1924.                             {
  1925.                                 double                        LeftWeight;
  1926.                                 double                        RightWeight;
  1927.                                 long                            LeftIndex;
  1928.                                 long                            RightIndex;
  1929.                                 double                        PrecisePositioning;
  1930.                                 double                        LeftValue;
  1931.                                 double                        RightValue;
  1932.                                 double                        ResultantComposite;
  1933.  
  1934.                                 PrecisePositioning = (double)NewFrameScan / (double)NewNumFrames
  1935.                                     * (double)OriginalNumFrames;
  1936.                                 LeftIndex = (long)PrecisePositioning;
  1937.                                 RightIndex = LeftIndex + 1;
  1938.                                 RightWeight = PrecisePositioning - LeftIndex;
  1939.                                 LeftWeight = 1 - RightWeight;
  1940.                                 LeftValue = largefixed2double(WaveTableStorDispGetFrame(
  1941.                                     Window->WaveTableData,TableScan,LeftIndex));
  1942.                                 RightValue = largefixed2double(WaveTableStorDispGetFrame(
  1943.                                     Window->WaveTableData,TableScan,RightIndex % OriginalNumFrames));
  1944.                                 ResultantComposite = LeftValue * LeftWeight
  1945.                                     + RightValue * RightWeight;
  1946.                                 WaveTableStorDispSetFrame(NewTable,TableScan,NewFrameScan,
  1947.                                     double2largefixed(ResultantComposite));
  1948.                             }
  1949.                     }
  1950.             }
  1951.  
  1952.         /* this one handles averaging the frames for table compression */
  1953.         else
  1954.             {
  1955.                 long                            FoldingFactor;
  1956.  
  1957.                 FoldingFactor = OriginalNumFrames / NewNumFrames;
  1958.                 for (TableScan = 0; TableScan < NumberOfTables; TableScan += 1)
  1959.                     {
  1960.                         long                            NewFrameScan;
  1961.  
  1962.                         for (NewFrameScan = 0; NewFrameScan < NewNumFrames; NewFrameScan += 1)
  1963.                             {
  1964.                                 double                        Accumulator;
  1965.                                 long                            SumScan;
  1966.                                 double                        Average;
  1967.  
  1968.                                 Accumulator = 0;
  1969.                                 for (SumScan = 0; SumScan < FoldingFactor; SumScan += 1)
  1970.                                     {
  1971.                                         Accumulator += largefixed2double(WaveTableStorDispGetFrame(
  1972.                                             Window->WaveTableData,TableScan,
  1973.                                             NewFrameScan * FoldingFactor + SumScan));
  1974.                                     }
  1975.                                 Average = Accumulator / FoldingFactor;
  1976.                                 WaveTableStorDispSetFrame(NewTable,TableScan,NewFrameScan,
  1977.                                     double2largefixed(Average));
  1978.                             }
  1979.                     }
  1980.             }
  1981.  
  1982.         Window->UndoBackupWaveTable = Window->WaveTableData;
  1983.         Window->WaveTableData = NewTable;
  1984.         WaveTableWindowUpdateAllParameters(Window);
  1985.         Window->WaveDataModified = True;
  1986.     }
  1987.  
  1988.  
  1989. /* argument list for wave table function thang */
  1990. static FunctionParamRec        ArgumentList[] =
  1991.     {
  1992.         {"frames",eInteger},
  1993.         {"tables",eInteger},
  1994.         {"data",eArrayOfFixed}
  1995.     };
  1996. #define ARGLISTLENGTH (sizeof(ArgumentList) / sizeof(ArgumentList[0]))
  1997.  
  1998.  
  1999. /* evaluate the wave formula and update the wave data */
  2000. void                                WaveTableWindowEvaluateFunction(WaveTableWindowRec* Window)
  2001.     {
  2002.         char*                                Blob;
  2003.         PcodeRec*                        FuncCode;
  2004.         CompileErrors                Error;
  2005.         long                                LineNumber;
  2006.         ParamStackRec*            ParamList;
  2007.         EvalErrors                    OtherError;
  2008.         OpcodeRec*                    ErrorOpcode;
  2009.         long                                OffendingInstruction;
  2010.         DataTypes                        ReturnType;
  2011.         long                                TotalFramesPerTable;
  2012.         long                                TotalNumTables;
  2013.  
  2014.         CheckPtrExistence(Window);
  2015.  
  2016.         /* bring the world up to date */
  2017.         if (!MainWindowMakeUpToDateFunctions(Window->MainWindow))
  2018.             {
  2019.                 return;
  2020.             }
  2021.  
  2022.         /* prepare the text blob to be evaluated */
  2023.         Blob = TextEditGetRawData(Window->FunctionEdit,"\x0a");
  2024.         if (Blob == NIL)
  2025.             {
  2026.              FailurePoint1:
  2027.                 AlertHalt("There is not enough memory available to compile the expression.",NIL);
  2028.                 return;
  2029.             }
  2030.  
  2031.         if (Window->UndoBackupWaveTable != NIL)
  2032.             {
  2033.                 DisposeWaveTableStorDisp(Window->UndoBackupWaveTable);
  2034.                 Window->UndoBackupWaveTable = NIL;
  2035.             }
  2036.  
  2037.         /* perform compilation */
  2038.         Error = CompileSpecialFunction(ArgumentList,ARGLISTLENGTH,&LineNumber,
  2039.             &ReturnType,Blob,&FuncCode);
  2040.         ReleasePtr(Blob);
  2041.         if (Error != eCompileNoError)
  2042.             {
  2043.                 SetTextEditSelection(Window->FunctionEdit,LineNumber - 1,0,LineNumber,0);
  2044.                 TextEditShowSelection(Window->FunctionEdit);
  2045.                 AlertHalt("A compile error occurred:  _",GetCompileErrorString(Error));
  2046.                 return;
  2047.             }
  2048.  
  2049.         /* try to evaluate the code */
  2050.         ParamList = NewParamStack();
  2051.         if (ParamList == NIL)
  2052.             {
  2053.              SecondFailurePoint1:
  2054.                 DisposePcode(FuncCode);
  2055.                 AlertHalt("There is not enough memory available to evaluate the expression.",NIL);
  2056.                 return;
  2057.             }
  2058.         TotalFramesPerTable = WaveTableWindowGetNumFramesPerTable(Window);
  2059.         TotalNumTables = WaveTableWindowGetNumTables(Window);
  2060.         /* add a space for the return value */
  2061.         if (!AddIntegerToStack(ParamList,0))
  2062.             {
  2063.              SecondFailurePoint2:
  2064.                 DisposeParamStack(ParamList);
  2065.                 goto SecondFailurePoint1;
  2066.             }
  2067.         /* frames */
  2068.         if (!AddIntegerToStack(ParamList,TotalFramesPerTable))
  2069.             {
  2070.                 goto SecondFailurePoint2;
  2071.             }
  2072.         /* tables */
  2073.         if (!AddIntegerToStack(ParamList,TotalNumTables))
  2074.             {
  2075.                 goto SecondFailurePoint2;
  2076.             }
  2077.         /* data */
  2078.         {
  2079.             largefixedsigned*        TheDataBlock;
  2080.             long                                TableScan;
  2081.             long                                FrameScan;
  2082.  
  2083.             TheDataBlock = (largefixedsigned*)AllocPtrCanFail(sizeof(largefixedsigned)
  2084.                 * TotalFramesPerTable * TotalNumTables,"WaveTableWindowEvaluateFunction: array");
  2085.             if (TheDataBlock == NIL)
  2086.                 {
  2087.                     goto SecondFailurePoint2;
  2088.                 }
  2089.             for (TableScan = 0; TableScan < TotalNumTables; TableScan += 1)
  2090.                 {
  2091.                     for (FrameScan = 0; FrameScan < TotalFramesPerTable; FrameScan += 1)
  2092.                         {
  2093.                             PRNGCHK(TheDataBlock,&(TheDataBlock[TableScan * TotalFramesPerTable
  2094.                                 + FrameScan]),sizeof(TheDataBlock[TableScan * TotalFramesPerTable
  2095.                                 + FrameScan]));
  2096.                             TheDataBlock[TableScan * TotalFramesPerTable + FrameScan]
  2097.                                 = WaveTableStorDispGetFrame(Window->WaveTableData,TableScan,FrameScan);
  2098.                         }
  2099.                 }
  2100.             if (!AddArrayToStack(ParamList,TheDataBlock))
  2101.                 {
  2102.                     ReleasePtr((char*)TheDataBlock);
  2103.                     goto SecondFailurePoint2;
  2104.                 }
  2105.         }
  2106.  
  2107.         /* executing the actual code */
  2108.         OtherError = EvaluatePcode(ParamList,FuncCode,
  2109.             Window->CodeCenter,&ErrorOpcode,&OffendingInstruction,Window->MainWindow,
  2110.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleLeftCopy,
  2111.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleRightCopy,
  2112.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleMonoCopy,
  2113.             (SampleErrors (*)(void*,char*,long*))&MainWindowGetWaveTableFrameCount,
  2114.             (SampleErrors (*)(void*,char*,long*))&MainWindowGetWaveTableTableCount,
  2115.             (SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetWaveTableArray,
  2116.             Window->MainWindow,
  2117.             (struct InteractionWindowRec* (*)(void*))&MainWindowGetInteractionWindow);
  2118.         if (OtherError != eEvalNoError)
  2119.             {
  2120.                 char*                    FuncNameString;
  2121.                 FuncCodeRec*    ErrorFunction;
  2122.                 MyBoolean            SuccessFlag;
  2123.  
  2124.                 /* present error message */
  2125.                 SuccessFlag = False;
  2126.                 ErrorFunction = GetFunctionFromOpcode(Window->CodeCenter,ErrorOpcode);
  2127.                 if (ErrorFunction == NIL)
  2128.                     {
  2129.                         FuncNameString = StringToBlockCopy("<anonymous>");
  2130.                     }
  2131.                  else
  2132.                     {
  2133.                         FuncNameString = CopyPtr(GetFunctionName(ErrorFunction));
  2134.                     }
  2135.                 if (FuncNameString != NIL)
  2136.                     {
  2137.                         char*                    Key;
  2138.  
  2139.                         Key = StringToBlockCopy("_");
  2140.                         if (Key != NIL)
  2141.                             {
  2142.                                 char*                    BaseMessage;
  2143.  
  2144.                                 BaseMessage = StringFromRaw("Error in function _, instruction _:  _");
  2145.                                 if (BaseMessage != NIL)
  2146.                                     {
  2147.                                         char*                    FixedMessage1;
  2148.  
  2149.                                         FixedMessage1 = ReplaceBlockCopy(BaseMessage,Key,FuncNameString);
  2150.                                         if (FixedMessage1 != NIL)
  2151.                                             {
  2152.                                                 char*                    NumberStr;
  2153.  
  2154.                                                 NumberStr = IntegerToString(OffendingInstruction);
  2155.                                                 if (NumberStr != NIL)
  2156.                                                     {
  2157.                                                         char*                    FixedMessage2;
  2158.  
  2159.                                                         FixedMessage2 = ReplaceBlockCopy(FixedMessage1,Key,NumberStr);
  2160.                                                         if (FixedMessage2 != NIL)
  2161.                                                             {
  2162.                                                                 AlertHalt(FixedMessage2,GetPcodeErrorMessage(OtherError));
  2163.                                                                 SuccessFlag = True;
  2164.                                                                 ReleasePtr(FixedMessage2);
  2165.                                                             }
  2166.                                                         ReleasePtr(NumberStr);
  2167.                                                     }
  2168.                                                 ReleasePtr(FixedMessage1);
  2169.                                             }
  2170.                                         ReleasePtr(BaseMessage);
  2171.                                     }
  2172.                                 ReleasePtr(Key);
  2173.                             }
  2174.                         ReleasePtr(FuncNameString);
  2175.                     }
  2176.                 if (!SuccessFlag)
  2177.                     {
  2178.                         AlertHalt("There is not enough memory available to show "
  2179.                             "the compile error message.",NIL);
  2180.                     }
  2181.                 DisposeParamStack(ParamList);
  2182.                 DisposePcode(FuncCode);
  2183.                 return;
  2184.             }
  2185.  
  2186.         /* get the data out */
  2187.         {
  2188.             largefixedsigned*            DataBlock;
  2189.             WaveTableStorDispRec*    NewWaveTable;
  2190.             long                                    TableScan;
  2191.             long                                    FrameScan;
  2192.  
  2193.             DataBlock = (largefixedsigned*)GetStackArray(ParamList,3);
  2194.             CheckPtrExistence((char*)DataBlock);
  2195.             NewWaveTable = NewWaveTableStorDisp(WaveTableStorDispNumBits(
  2196.                 Window->WaveTableData),TotalFramesPerTable);
  2197.             if (NewWaveTable == NIL)
  2198.                 {
  2199.                  FinishedSideNoMemory1:
  2200.                     AlertHalt("There is not enough memory available to build the wave.",NIL);
  2201.                     DisposeParamStack(ParamList);
  2202.                     DisposePcode(FuncCode);
  2203.                     return;
  2204.                 }
  2205.             for (TableScan = 0; TableScan < TotalNumTables; TableScan += 1)
  2206.                 {
  2207.                     if (!WaveTableStorDispAppendEntry(NewWaveTable))
  2208.                         {
  2209.                          FinishedSideNoMemory2:
  2210.                             DisposeWaveTableStorDisp(NewWaveTable);
  2211.                             goto FinishedSideNoMemory1;
  2212.                         }
  2213.                 }
  2214.             for (TableScan = 0; TableScan < TotalNumTables; TableScan += 1)
  2215.                 {
  2216.                     for (FrameScan = 0; FrameScan < TotalFramesPerTable; FrameScan += 1)
  2217.                         {
  2218.                             PRNGCHK(DataBlock,&(DataBlock[TableScan * TotalFramesPerTable + FrameScan]),
  2219.                                 sizeof(DataBlock[TableScan * TotalFramesPerTable + FrameScan]));
  2220.                             WaveTableStorDispSetFrame(NewWaveTable,TableScan,FrameScan,
  2221.                                 DataBlock[TableScan * TotalFramesPerTable + FrameScan]);
  2222.                         }
  2223.                 }
  2224.             Window->UndoBackupWaveTable = Window->WaveTableData;
  2225.             Window->WaveTableData = NewWaveTable;
  2226.             Window->WaveDataModified = True;
  2227.         }
  2228.         DisposeParamStack(ParamList); /* disposes our array for us */
  2229.         DisposePcode(FuncCode);
  2230.         WaveTableWindowUpdateAllParameters(Window);
  2231.     }
  2232.  
  2233.  
  2234. /* get a copy of the wave data array */
  2235. largefixedsigned*        WaveTableWindowGetWaveArray(WaveTableWindowRec* Window)
  2236.     {
  2237.         largefixedsigned*    Array;
  2238.         long                            TableLimit;
  2239.         long                            FrameLimit;
  2240.         long                            TableScan;
  2241.  
  2242.         CheckPtrExistence(Window);
  2243.         TableLimit = WaveTableStorDispNumTables(Window->WaveTableData);
  2244.         FrameLimit = WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  2245.         Array = (largefixedsigned*)AllocPtrCanFail(TableLimit * FrameLimit
  2246.             * sizeof(largefixedsigned),"WaveTableWindowGetWaveArray");
  2247.         if (Array != NIL)
  2248.             {
  2249.                 for (TableScan = 0; TableScan < TableLimit; TableScan += 1)
  2250.                     {
  2251.                         long                            FrameScan;
  2252.  
  2253.                         for (FrameScan = 0; FrameScan < FrameLimit; FrameScan += 1)
  2254.                             {
  2255.                                 PRNGCHK(Array,&(Array[TableScan * FrameLimit + FrameScan]),
  2256.                                     sizeof(Array[TableScan * FrameLimit + FrameScan]));
  2257.                                 Array[TableScan * FrameLimit + FrameScan]
  2258.                                     = WaveTableStorDispGetFrame(Window->WaveTableData,
  2259.                                     TableScan,FrameScan);
  2260.                             }
  2261.                     }
  2262.             }
  2263.         return Array;
  2264.     }
  2265.  
  2266.  
  2267. /* force the wave data to be written back to the object.  this does not write back */
  2268. /* any other data. */
  2269. MyBoolean                        WaveTableWindowForceWaveTableUpdate(WaveTableWindowRec* Window)
  2270.     {
  2271.         WaveTableStorageRec*        NewWaveTable;
  2272.  
  2273.         CheckPtrExistence(Window);
  2274.  
  2275.         NewWaveTable = NewWaveTableStorage(WaveTableStorDispNumBits(Window->WaveTableData),
  2276.             WaveTableStorDispNumFramesPerTable(Window->WaveTableData));
  2277.         if (NewWaveTable != NIL)
  2278.             {
  2279.                 long                                        Limit;
  2280.                 long                                        Scan;
  2281.  
  2282.                 Limit = WaveTableStorDispNumTables(Window->WaveTableData);
  2283.                 for (Scan = 0; Scan < Limit; Scan += 1)
  2284.                     {
  2285.                         long                            Index;
  2286.                         long                            IndexLimit;
  2287.  
  2288.                         if (!WaveTableStorageAppendEntry(NewWaveTable))
  2289.                             {
  2290.                                 DisposeWaveTableStorage(NewWaveTable);
  2291.                                 return False;
  2292.                             }
  2293.                         IndexLimit = WaveTableStorDispNumFramesPerTable(Window->WaveTableData);
  2294.                         for (Index = 0; Index < IndexLimit; Index += 1)
  2295.                             {
  2296.                                 WaveTableStorageSetFrame(NewWaveTable,Scan,Index,
  2297.                                     WaveTableStorDispGetFrame(Window->WaveTableData,Scan,Index));
  2298.                             }
  2299.                     }
  2300.                 WaveTableObjectPutNewData(Window->WaveTableObject,NewWaveTable);
  2301.                 return True;
  2302.             }
  2303.          else
  2304.             {
  2305.                 return False;
  2306.             }
  2307.     }
  2308.  
  2309.  
  2310. /* force all data to be written back to the object.  this includes calling */
  2311. /* WaveTableWindowForceWaveTableUpdate() */
  2312. MyBoolean                        WaveTableWindowWritebackModifiedData(WaveTableWindowRec* Window)
  2313.     {
  2314.         MyBoolean                    SuccessFlag = True;
  2315.  
  2316.         CheckPtrExistence(Window);
  2317.  
  2318.         if (TextEditDoesItNeedToBeSaved(Window->NameEdit))
  2319.             {
  2320.                 char*                        String;
  2321.  
  2322.                 String = WaveTableWindowGetNameCopy(Window);
  2323.                 if (String != NIL)
  2324.                     {
  2325.                         WaveTableObjectNewName(Window->WaveTableObject,String);
  2326.                         TextEditHasBeenSaved(Window->NameEdit);
  2327.                     }
  2328.                  else
  2329.                     {
  2330.                         SuccessFlag = False;
  2331.                     }
  2332.             }
  2333.  
  2334.         if (TextEditDoesItNeedToBeSaved(Window->FunctionEdit))
  2335.             {
  2336.                 char*                        String;
  2337.  
  2338.                 String = WaveTableWindowGetFormulaCopy(Window);
  2339.                 if (String != NIL)
  2340.                     {
  2341.                         WaveTableObjectNewFormula(Window->WaveTableObject,String);
  2342.                         TextEditHasBeenSaved(Window->FunctionEdit);
  2343.                     }
  2344.                  else
  2345.                     {
  2346.                         SuccessFlag = False;
  2347.                     }
  2348.             }
  2349.  
  2350.         if (TextEditDoesItNeedToBeSaved(Window->TestAttackDuration))
  2351.             {
  2352.                 char*                        String;
  2353.  
  2354.                 String = TextEditGetRawData(Window->TestAttackDuration,SYSTEMLINEFEED);
  2355.                 if (String != NIL)
  2356.                     {
  2357.                         SetWaveTableObjectTestAttack(Window->WaveTableObject,
  2358.                             StringToLongDouble(String,PtrSize(String)));
  2359.                         ReleasePtr(String);
  2360.                         TextEditHasBeenSaved(Window->TestAttackDuration);
  2361.                     }
  2362.                  else
  2363.                     {
  2364.                         SuccessFlag = False;
  2365.                     }
  2366.             }
  2367.  
  2368.         if (TextEditDoesItNeedToBeSaved(Window->TestDecayDuration))
  2369.             {
  2370.                 char*                        String;
  2371.  
  2372.                 String = TextEditGetRawData(Window->TestDecayDuration,SYSTEMLINEFEED);
  2373.                 if (String != NIL)
  2374.                     {
  2375.                         SetWaveTableObjectTestDecay(Window->WaveTableObject,
  2376.                             StringToLongDouble(String,PtrSize(String)));
  2377.                         ReleasePtr(String);
  2378.                         TextEditHasBeenSaved(Window->TestDecayDuration);
  2379.                     }
  2380.                  else
  2381.                     {
  2382.                         SuccessFlag = False;
  2383.                     }
  2384.             }
  2385.  
  2386.         if (TextEditDoesItNeedToBeSaved(Window->TestFrequency))
  2387.             {
  2388.                 char*                        String;
  2389.  
  2390.                 String = TextEditGetRawData(Window->TestFrequency,SYSTEMLINEFEED);
  2391.                 if (String != NIL)
  2392.                     {
  2393.                         SetWaveTableObjectTestPitch(Window->WaveTableObject,
  2394.                             StringToLongDouble(String,PtrSize(String)));
  2395.                         ReleasePtr(String);
  2396.                         TextEditHasBeenSaved(Window->TestFrequency);
  2397.                     }
  2398.                  else
  2399.                     {
  2400.                         SuccessFlag = False;
  2401.                     }
  2402.             }
  2403.  
  2404.         if (TextEditDoesItNeedToBeSaved(Window->TestSamplingRate))
  2405.             {
  2406.                 char*                        String;
  2407.  
  2408.                 String = TextEditGetRawData(Window->TestSamplingRate,SYSTEMLINEFEED);
  2409.                 if (String != NIL)
  2410.                     {
  2411.                         SetWaveTableObjectTestSamplingRate(Window->WaveTableObject,
  2412.                             StringToInteger(String,PtrSize(String)));
  2413.                         ReleasePtr(String);
  2414.                         TextEditHasBeenSaved(Window->TestSamplingRate);
  2415.                     }
  2416.                  else
  2417.                     {
  2418.                         SuccessFlag = False;
  2419.                     }
  2420.             }
  2421.  
  2422.         if (Window->WaveDataModified)
  2423.             {
  2424.                 if (WaveTableWindowForceWaveTableUpdate(Window))
  2425.                     {
  2426.                         Window->WaveDataModified = False;
  2427.                     }
  2428.                  else
  2429.                     {
  2430.                         SuccessFlag = False;
  2431.                     }
  2432.             }
  2433.  
  2434.         return SuccessFlag;
  2435.     }
  2436.